ARM: support syscall tracing
Subsystems (2)
PATCH 1/1 ARM: support syscall tracing
As specified by ftrace-design.txt, TIF_SYSCALL_TRACEPOINT was added, as well as NR_syscalls in asm/unistd.h. Additionally, __sys_trace was modified to call trace_sys_enter and trace_sys_exit when appropriate.
Tests #2 - #4 of "perf test" now complete successfully.
---
This patch is an update of one I posted some months ago. It has been rebased to Linus's current HEAD.
arch/arm/Kconfig | 1 + arch/arm/include/asm/syscall.h | 4 ++++ arch/arm/include/asm/thread_info.h | 2 ++ arch/arm/include/asm/unistd.h | 8 ++++++++ arch/arm/kernel/entry-common.S | 12 +++++++++++- arch/arm/kernel/ptrace.c | 23 ++++++++++++++++++----- 6 files changed, 44 insertions(+), 6 deletions(-)
arch/arm/Kconfig +1 -0
@@ -16,6 +16,7 @@ config ARM select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL select HAVE_ARCH_KGDB select HAVE_ARCH_TRACEHOOK + select HAVE_SYSCALL_TRACEPOINTS select HAVE_KPROBES if !XIP_KERNEL select HAVE_KRETPROBES if (HAVE_KPROBES) select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
arch/arm/include/asm/syscall.h +4 -0
@@ -9,6 +9,10 @@#include <linux/err.h> +#include <asm/unistd.h> + +#define NR_syscalls (__NR_syscalls) +extern const unsigned long sys_call_table[]; static inline int syscall_get_nr(struct task_struct *task,
arch/arm/include/asm/thread_info.h +2 -0
@@ -154,6 +154,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,#define TIF_RESTORE_SIGMASK 20#define TIF_SECCOMP 21#define TIF_SWITCH_MM 22/* deferred switch_mm */ +#define TIF_SYSCALL_TRACEPOINT 23#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
@@ -163,6 +164,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)#define _TIF_SECCOMP (1 << TIF_SECCOMP) +#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)/* Checks for any syscall work in entry-common.S */ #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT)
arch/arm/include/asm/unistd.h +8 -0
@@ -406,6 +406,14 @@#define __NR_process_vm_writev (__NR_SYSCALL_BASE+377)/* +* This may need to be greater than __NR_last_syscall+1 in order to +* account for the padding in the syscall table +*/ +#ifdef __KERNEL__ +#define __NR_syscalls (380) +#endif /* __KERNEL__ */ + +/* * The following SWIs are ARM private. */ #define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000)
arch/arm/kernel/entry-common.S +11 -1
@@ -94,6 +94,15 @@ ENDPROC(ret_from_fork) .equ NR_syscalls,0 #define CALL(x) .equ NR_syscalls,NR_syscalls+1 #include "calls.S" + +/* + * Ensure that the system call table is equal to __NR_syscalls, + * which is the value the rest of the system sees + */ +.ifne NR_syscalls - __NR_syscalls +.error "__NR_syscalls is not equal to the size of the syscall table" +.endif + #undef CALL #define CALL(x) .long x
@@ -415,7 +424,8 @@ local_restart: 1: #endif - tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls? + tst r10, #_TIF_SYSCALL_WORK + tsteq r10, #_TIF_SYSCALL_TRACEPOINT bne __sys_trace cmp scno, #NR_syscalls @ check upper syscall limit
arch/arm/kernel/ptrace.c +18 -5
@@ -30,6 +30,9 @@#include <asm/pgtable.h> #include <asm/traps.h> +#define CREATE_TRACE_POINTS +#include <trace/events/syscalls.h> +#define REG_PC 15#define REG_PSR 16/*
@@ -918,7 +921,8 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno, {unsigned long ip; -if (!test_thread_flag (TIF_SYSCALL_TRACE )) +if (!test_thread_flag (TIF_SYSCALL_TRACE ) && + !test_thread_flag (TIF_SYSCALL_TRACEPOINT ))return scno;current_thread_info ()->syscall = scno;
@@ -930,10 +934,19 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno, ip = regs->ARM_ip; regs->ARM_ip = dir; -if (dir ==PTRACE_SYSCALL_EXIT ) -tracehook_report_syscall_exit (regs,0 ); -else if (tracehook_report_syscall_entry (regs)) -current_thread_info ()->syscall =-1 ; +if (test_thread_flag (TIF_SYSCALL_TRACE )) { +if (dir ==PTRACE_SYSCALL_EXIT ) +tracehook_report_syscall_exit (regs,0 ); +else if (tracehook_report_syscall_entry (regs)) +current_thread_info ()->syscall =-1 ; + } + +if (test_thread_flag (TIF_SYSCALL_TRACEPOINT )) { +if (dir ==PTRACE_SYSCALL_EXIT ) +trace_sys_exit (regs, scno); +else +trace_sys_enter (regs, scno); + } regs->ARM_ip = ip;return current_thread_info ()->syscall;
Signature · 1 line
1.7.0.4
PATCH 1/1 ARM: support syscall tracing
Hi Wade,
Thanks for the new patch. A few comments inline.
Quoted 13 lines · Wade Farnsworth
arch/arm/include/asm/thread_info.h +1
-0@@ -154,6 +154,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,#define TIF_RESTORE_SIGMASK 20#define TIF_SECCOMP 21#define TIF_SWITCH_MM 22/* deferred switch_mm */ +#define TIF_SYSCALL_TRACEPOINT 23#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
arch/arm/include/asm/thread_info.h extern int vfp_restore_user_hwstate(struct user_vfp __user *, · line 167
Quoted 4 lines
arch/arm/include/asm/thread_info.h +1
-0@@ -163,6 +164,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)#define _TIF_SECCOMP (1 << TIF_SECCOMP) +#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
Can you add this to the definition of _TIF_SYSCALL_WORK as well please?
Quoted 21 lines
arch/arm/kernel/entry-common.S +9
-0@@ -94,6 +94,15 @@ ENDPROC(ret_from_fork) .equ NR_syscalls,0 #define CALL(x) .equ NR_syscalls,NR_syscalls+1 #include "calls.S" + +/* + * Ensure that the system call table is equal to __NR_syscalls, + * which is the value the rest of the system sees + */ +.ifne NR_syscalls - __NR_syscalls +.error "__NR_syscalls is not equal to the size of the syscall table" +.endif + #undef CALL #define CALL(x) .long x
arch/arm/kernel/entry-common.S local_restart: · line 429
Quoted 7 lines
arch/arm/kernel/entry-common.S +2
-1@@ -415,7 +424,8 @@ local_restart: 1: #endif - tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls? + tst r10, #_TIF_SYSCALL_WORK + tsteq r10, #_TIF_SYSCALL_TRACEPOINT bne __sys_trace
Then we don't need this hunk.
Quoted 35 lines
arch/arm/kernel/ptrace.c +8
-5@@ -30,6 +30,9 @@#include <asm/pgtable.h> #include <asm/traps.h> +#define CREATE_TRACE_POINTS +#include <trace/events/syscalls.h> +#define REG_PC 15#define REG_PSR 16/* @@ -918,7 +921,8 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno, {unsigned long ip; -if (!test_thread_flag (TIF_SYSCALL_TRACE )) +if (!test_thread_flag (TIF_SYSCALL_TRACE ) && + !test_thread_flag (TIF_SYSCALL_TRACEPOINT ))return scno;current_thread_info ()->syscall = scno;@@ -930,10 +934,19 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno, ip = regs->ARM_ip; regs->ARM_ip = dir; -if (dir ==PTRACE_SYSCALL_EXIT ) -tracehook_report_syscall_exit (regs,0 ); -else if (tracehook_report_syscall_entry (regs)) -current_thread_info ()->syscall =-1 ; +if (test_thread_flag (TIF_SYSCALL_TRACE )) { +if (dir ==PTRACE_SYSCALL_EXIT ) +tracehook_report_syscall_exit (regs,0 );
arch/arm/kernel/ptrace.c static int ptrace_syscall_trace(struct pt_regs *regs, int scno, · line 949
Quoted 10 lines
arch/arm/kernel/ptrace.c +10
-0+else if (tracehook_report_syscall_entry (regs)) +current_thread_info ()->syscall =-1 ; + } + +if (test_thread_flag (TIF_SYSCALL_TRACEPOINT )) { +if (dir ==PTRACE_SYSCALL_EXIT ) +trace_sys_exit (regs, scno); +else +trace_sys_enter (regs, scno); + }
I reckon the TRACEPOINT stuff would be better off inside the syscall_trace_{enter,exit} functions. They don't modify the syscall number, so they can just use the return value from ptrace_syscall_trace before the audit hook invoked.
Will