#include #include #include #include "trace_output.h" #include "trace.h" static atomic_t refcount; void start_ftrace_syscalls(void) { unsigned long flags; struct task_struct *g, *t; if (atomic_inc_return(&refcount) != 1) goto out; read_lock_irqsave(&tasklist_lock, flags); do_each_thread(g, t) { set_tsk_thread_flag(t, TIF_SYSCALL_FTRACE); } while_each_thread(g, t); read_unlock_irqrestore(&tasklist_lock, flags); out: atomic_dec(&refcount); } void stop_ftrace_syscalls(void) { unsigned long flags; struct task_struct *g, *t; if (atomic_dec_return(&refcount)) goto out; read_lock_irqsave(&tasklist_lock, flags); do_each_thread(g, t) { clear_tsk_thread_flag(t, TIF_SYSCALL_FTRACE); } while_each_thread(g, t); read_unlock_irqrestore(&tasklist_lock, flags); out: atomic_inc(&refcount); } void ftrace_syscall_enter(struct pt_regs *regs) { int syscall_nr; syscall_nr = syscall_get_nr(current, regs); trace_printk("syscall %d enter\n", syscall_nr); } void ftrace_syscall_exit(struct pt_regs *regs) { int syscall_nr; syscall_nr = syscall_get_nr(current, regs); trace_printk("syscall %d exit\n", syscall_nr); } static int init_syscall_tracer(struct trace_array *tr) { start_ftrace_syscalls(); return 0; } static void reset_syscall_tracer(struct trace_array *tr) { stop_ftrace_syscalls(); } static struct trace_event syscall_enter_event = { .type = TRACE_SYSCALL_ENTER, }; static struct trace_event syscall_exit_event = { .type = TRACE_SYSCALL_EXIT, }; static struct tracer syscall_tracer __read_mostly = { .name = "syscall", .init = init_syscall_tracer, .reset = reset_syscall_tracer }; __init int register_ftrace_syscalls(void) { int ret; ret = register_ftrace_event(&syscall_enter_event); if (!ret) { printk(KERN_WARNING "event %d failed to register\n", syscall_enter_event.type); WARN_ON_ONCE(1); } ret = register_ftrace_event(&syscall_exit_event); if (!ret) { printk(KERN_WARNING "event %d failed to register\n", syscall_exit_event.type); WARN_ON_ONCE(1); } return register_tracer(&syscall_tracer); } device_initcall(register_ftrace_syscalls);