Loading arch/x86/include/asm/ftrace.h +24 −0 Original line number Diff line number Diff line Loading @@ -72,4 +72,28 @@ int ftrace_int3_handler(struct pt_regs *regs); #endif /* __ASSEMBLY__ */ #endif /* CONFIG_FUNCTION_TRACER */ #if !defined(__ASSEMBLY__) && !defined(COMPILE_OFFSETS) #if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_IA32_EMULATION) #include <asm/compat.h> /* * Because ia32 syscalls do not map to x86_64 syscall numbers * this screws up the trace output when tracing a ia32 task. * Instead of reporting bogus syscalls, just do not trace them. * * If the user realy wants these, then they should use the * raw syscall tracepoints with filtering. */ #define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS 1 static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs) { if (is_compat_task()) return true; return false; } #endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_IA32_EMULATION */ #endif /* !__ASSEMBLY__ && !COMPILE_OFFSETS */ #endif /* _ASM_X86_FTRACE_H */ arch/x86/include/asm/thread_info.h +0 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ struct task_struct; struct exec_domain; #include <asm/processor.h> #include <asm/ftrace.h> #include <linux/atomic.h> struct thread_info { Loading kernel/trace/ftrace.c +32 −14 Original line number Diff line number Diff line Loading @@ -3996,37 +3996,51 @@ static void ftrace_init_module(struct module *mod, ftrace_process_locs(mod, start, end); } static int ftrace_module_notify(struct notifier_block *self, static int ftrace_module_notify_enter(struct notifier_block *self, unsigned long val, void *data) { struct module *mod = data; switch (val) { case MODULE_STATE_COMING: if (val == MODULE_STATE_COMING) ftrace_init_module(mod, mod->ftrace_callsites, mod->ftrace_callsites + mod->num_ftrace_callsites); break; case MODULE_STATE_GOING: ftrace_release_mod(mod); break; return 0; } static int ftrace_module_notify_exit(struct notifier_block *self, unsigned long val, void *data) { struct module *mod = data; if (val == MODULE_STATE_GOING) ftrace_release_mod(mod); return 0; } #else static int ftrace_module_notify(struct notifier_block *self, static int ftrace_module_notify_enter(struct notifier_block *self, unsigned long val, void *data) { return 0; } static int ftrace_module_notify_exit(struct notifier_block *self, unsigned long val, void *data) { return 0; } #endif /* CONFIG_MODULES */ struct notifier_block ftrace_module_nb = { .notifier_call = ftrace_module_notify, struct notifier_block ftrace_module_enter_nb = { .notifier_call = ftrace_module_notify_enter, .priority = INT_MAX, /* Run before anything that can use kprobes */ }; struct notifier_block ftrace_module_exit_nb = { .notifier_call = ftrace_module_notify_exit, .priority = INT_MIN, /* Run after anything that can remove kprobes */ }; extern unsigned long __start_mcount_loc[]; extern unsigned long __stop_mcount_loc[]; Loading Loading @@ -4058,9 +4072,13 @@ void __init ftrace_init(void) __start_mcount_loc, __stop_mcount_loc); ret = register_module_notifier(&ftrace_module_nb); ret = register_module_notifier(&ftrace_module_enter_nb); if (ret) pr_warning("Failed to register trace ftrace module enter notifier\n"); ret = register_module_notifier(&ftrace_module_exit_nb); if (ret) pr_warning("Failed to register trace ftrace module notifier\n"); pr_warning("Failed to register trace ftrace module exit notifier\n"); set_ftrace_early_filters(); Loading kernel/trace/trace_syscalls.c +38 −5 Original line number Diff line number Diff line #include <trace/syscall.h> #include <trace/events/syscalls.h> #include <linux/syscalls.h> #include <linux/slab.h> #include <linux/kernel.h> #include <linux/module.h> /* for MODULE_NAME_LEN via KSYM_SYMBOL_LEN */ Loading Loading @@ -47,6 +48,38 @@ static inline bool arch_syscall_match_sym_name(const char *sym, const char *name } #endif #ifdef ARCH_TRACE_IGNORE_COMPAT_SYSCALLS /* * Some architectures that allow for 32bit applications * to run on a 64bit kernel, do not map the syscalls for * the 32bit tasks the same as they do for 64bit tasks. * * *cough*x86*cough* * * In such a case, instead of reporting the wrong syscalls, * simply ignore them. * * For an arch to ignore the compat syscalls it needs to * define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS as well as * define the function arch_trace_is_compat_syscall() to let * the tracing system know that it should ignore it. */ static int trace_get_syscall_nr(struct task_struct *task, struct pt_regs *regs) { if (unlikely(arch_trace_is_compat_syscall(regs))) return -1; return syscall_get_nr(task, regs); } #else static inline int trace_get_syscall_nr(struct task_struct *task, struct pt_regs *regs) { return syscall_get_nr(task, regs); } #endif /* ARCH_TRACE_IGNORE_COMPAT_SYSCALLS */ static __init struct syscall_metadata * find_syscall_meta(unsigned long syscall) { Loading Loading @@ -276,10 +309,10 @@ static void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id) struct syscall_metadata *sys_data; struct ring_buffer_event *event; struct ring_buffer *buffer; int size; int syscall_nr; int size; syscall_nr = syscall_get_nr(current, regs); syscall_nr = trace_get_syscall_nr(current, regs); if (syscall_nr < 0) return; if (!test_bit(syscall_nr, enabled_enter_syscalls)) Loading Loading @@ -313,7 +346,7 @@ static void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret) struct ring_buffer *buffer; int syscall_nr; syscall_nr = syscall_get_nr(current, regs); syscall_nr = trace_get_syscall_nr(current, regs); if (syscall_nr < 0) return; if (!test_bit(syscall_nr, enabled_exit_syscalls)) Loading Loading @@ -502,7 +535,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) int rctx; int size; syscall_nr = syscall_get_nr(current, regs); syscall_nr = trace_get_syscall_nr(current, regs); if (syscall_nr < 0) return; if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) Loading Loading @@ -578,7 +611,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) int rctx; int size; syscall_nr = syscall_get_nr(current, regs); syscall_nr = trace_get_syscall_nr(current, regs); if (syscall_nr < 0) return; if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) Loading Loading
arch/x86/include/asm/ftrace.h +24 −0 Original line number Diff line number Diff line Loading @@ -72,4 +72,28 @@ int ftrace_int3_handler(struct pt_regs *regs); #endif /* __ASSEMBLY__ */ #endif /* CONFIG_FUNCTION_TRACER */ #if !defined(__ASSEMBLY__) && !defined(COMPILE_OFFSETS) #if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_IA32_EMULATION) #include <asm/compat.h> /* * Because ia32 syscalls do not map to x86_64 syscall numbers * this screws up the trace output when tracing a ia32 task. * Instead of reporting bogus syscalls, just do not trace them. * * If the user realy wants these, then they should use the * raw syscall tracepoints with filtering. */ #define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS 1 static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs) { if (is_compat_task()) return true; return false; } #endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_IA32_EMULATION */ #endif /* !__ASSEMBLY__ && !COMPILE_OFFSETS */ #endif /* _ASM_X86_FTRACE_H */
arch/x86/include/asm/thread_info.h +0 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ struct task_struct; struct exec_domain; #include <asm/processor.h> #include <asm/ftrace.h> #include <linux/atomic.h> struct thread_info { Loading
kernel/trace/ftrace.c +32 −14 Original line number Diff line number Diff line Loading @@ -3996,37 +3996,51 @@ static void ftrace_init_module(struct module *mod, ftrace_process_locs(mod, start, end); } static int ftrace_module_notify(struct notifier_block *self, static int ftrace_module_notify_enter(struct notifier_block *self, unsigned long val, void *data) { struct module *mod = data; switch (val) { case MODULE_STATE_COMING: if (val == MODULE_STATE_COMING) ftrace_init_module(mod, mod->ftrace_callsites, mod->ftrace_callsites + mod->num_ftrace_callsites); break; case MODULE_STATE_GOING: ftrace_release_mod(mod); break; return 0; } static int ftrace_module_notify_exit(struct notifier_block *self, unsigned long val, void *data) { struct module *mod = data; if (val == MODULE_STATE_GOING) ftrace_release_mod(mod); return 0; } #else static int ftrace_module_notify(struct notifier_block *self, static int ftrace_module_notify_enter(struct notifier_block *self, unsigned long val, void *data) { return 0; } static int ftrace_module_notify_exit(struct notifier_block *self, unsigned long val, void *data) { return 0; } #endif /* CONFIG_MODULES */ struct notifier_block ftrace_module_nb = { .notifier_call = ftrace_module_notify, struct notifier_block ftrace_module_enter_nb = { .notifier_call = ftrace_module_notify_enter, .priority = INT_MAX, /* Run before anything that can use kprobes */ }; struct notifier_block ftrace_module_exit_nb = { .notifier_call = ftrace_module_notify_exit, .priority = INT_MIN, /* Run after anything that can remove kprobes */ }; extern unsigned long __start_mcount_loc[]; extern unsigned long __stop_mcount_loc[]; Loading Loading @@ -4058,9 +4072,13 @@ void __init ftrace_init(void) __start_mcount_loc, __stop_mcount_loc); ret = register_module_notifier(&ftrace_module_nb); ret = register_module_notifier(&ftrace_module_enter_nb); if (ret) pr_warning("Failed to register trace ftrace module enter notifier\n"); ret = register_module_notifier(&ftrace_module_exit_nb); if (ret) pr_warning("Failed to register trace ftrace module notifier\n"); pr_warning("Failed to register trace ftrace module exit notifier\n"); set_ftrace_early_filters(); Loading
kernel/trace/trace_syscalls.c +38 −5 Original line number Diff line number Diff line #include <trace/syscall.h> #include <trace/events/syscalls.h> #include <linux/syscalls.h> #include <linux/slab.h> #include <linux/kernel.h> #include <linux/module.h> /* for MODULE_NAME_LEN via KSYM_SYMBOL_LEN */ Loading Loading @@ -47,6 +48,38 @@ static inline bool arch_syscall_match_sym_name(const char *sym, const char *name } #endif #ifdef ARCH_TRACE_IGNORE_COMPAT_SYSCALLS /* * Some architectures that allow for 32bit applications * to run on a 64bit kernel, do not map the syscalls for * the 32bit tasks the same as they do for 64bit tasks. * * *cough*x86*cough* * * In such a case, instead of reporting the wrong syscalls, * simply ignore them. * * For an arch to ignore the compat syscalls it needs to * define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS as well as * define the function arch_trace_is_compat_syscall() to let * the tracing system know that it should ignore it. */ static int trace_get_syscall_nr(struct task_struct *task, struct pt_regs *regs) { if (unlikely(arch_trace_is_compat_syscall(regs))) return -1; return syscall_get_nr(task, regs); } #else static inline int trace_get_syscall_nr(struct task_struct *task, struct pt_regs *regs) { return syscall_get_nr(task, regs); } #endif /* ARCH_TRACE_IGNORE_COMPAT_SYSCALLS */ static __init struct syscall_metadata * find_syscall_meta(unsigned long syscall) { Loading Loading @@ -276,10 +309,10 @@ static void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id) struct syscall_metadata *sys_data; struct ring_buffer_event *event; struct ring_buffer *buffer; int size; int syscall_nr; int size; syscall_nr = syscall_get_nr(current, regs); syscall_nr = trace_get_syscall_nr(current, regs); if (syscall_nr < 0) return; if (!test_bit(syscall_nr, enabled_enter_syscalls)) Loading Loading @@ -313,7 +346,7 @@ static void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret) struct ring_buffer *buffer; int syscall_nr; syscall_nr = syscall_get_nr(current, regs); syscall_nr = trace_get_syscall_nr(current, regs); if (syscall_nr < 0) return; if (!test_bit(syscall_nr, enabled_exit_syscalls)) Loading Loading @@ -502,7 +535,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) int rctx; int size; syscall_nr = syscall_get_nr(current, regs); syscall_nr = trace_get_syscall_nr(current, regs); if (syscall_nr < 0) return; if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) Loading Loading @@ -578,7 +611,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) int rctx; int size; syscall_nr = syscall_get_nr(current, regs); syscall_nr = trace_get_syscall_nr(current, regs); if (syscall_nr < 0) return; if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) Loading