mirror of
https://github.com/adulau/aha.git
synced 2025-01-03 22:53:18 +00:00
sh: Add ftrace syscall tracing support
Now that I've added TIF_SYSCALL_FTRACE the thread flags do not fit into a single byte any more. Code testing them now needs to be aware of the upper and lower bytes. Signed-off-by: Matt Fleming <matt@console-pimps.org> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
parent
c1340c053b
commit
c652d780c9
8 changed files with 100 additions and 10 deletions
|
@ -32,6 +32,7 @@ config SUPERH32
|
||||||
select HAVE_FTRACE_MCOUNT_RECORD
|
select HAVE_FTRACE_MCOUNT_RECORD
|
||||||
select HAVE_DYNAMIC_FTRACE
|
select HAVE_DYNAMIC_FTRACE
|
||||||
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
|
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
|
||||||
|
select HAVE_FTRACE_SYSCALLS
|
||||||
select HAVE_ARCH_KGDB
|
select HAVE_ARCH_KGDB
|
||||||
select ARCH_HIBERNATION_POSSIBLE if MMU
|
select ARCH_HIBERNATION_POSSIBLE if MMU
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ static inline void syscall_get_arguments(struct task_struct *task,
|
||||||
case 3: args[2] = regs->regs[6];
|
case 3: args[2] = regs->regs[6];
|
||||||
case 2: args[1] = regs->regs[5];
|
case 2: args[1] = regs->regs[5];
|
||||||
case 1: args[0] = regs->regs[4];
|
case 1: args[0] = regs->regs[4];
|
||||||
|
case 0:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
|
|
|
@ -97,7 +97,7 @@ static inline struct thread_info *current_thread_info(void)
|
||||||
|
|
||||||
extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
|
extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
|
||||||
extern void free_thread_info(struct thread_info *ti);
|
extern void free_thread_info(struct thread_info *ti);
|
||||||
|
|
||||||
#endif /* THREAD_SHIFT < PAGE_SHIFT */
|
#endif /* THREAD_SHIFT < PAGE_SHIFT */
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
|
@ -116,6 +116,7 @@ extern void free_thread_info(struct thread_info *ti);
|
||||||
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
|
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
|
||||||
#define TIF_SECCOMP 6 /* secure computing */
|
#define TIF_SECCOMP 6 /* secure computing */
|
||||||
#define TIF_NOTIFY_RESUME 7 /* callback before returning to user */
|
#define TIF_NOTIFY_RESUME 7 /* callback before returning to user */
|
||||||
|
#define TIF_SYSCALL_FTRACE 8 /* for ftrace syscall instrumentation */
|
||||||
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
|
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
|
||||||
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
|
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
|
||||||
#define TIF_MEMDIE 18
|
#define TIF_MEMDIE 18
|
||||||
|
@ -129,25 +130,27 @@ extern void free_thread_info(struct thread_info *ti);
|
||||||
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
||||||
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
|
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
|
||||||
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
||||||
|
#define _TIF_SYSCALL_FTRACE (1 << TIF_SYSCALL_FTRACE)
|
||||||
#define _TIF_USEDFPU (1 << TIF_USEDFPU)
|
#define _TIF_USEDFPU (1 << TIF_USEDFPU)
|
||||||
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
|
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
|
||||||
#define _TIF_FREEZE (1 << TIF_FREEZE)
|
#define _TIF_FREEZE (1 << TIF_FREEZE)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within a byte, or we
|
* _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within 2 bytes, or we
|
||||||
* blow the tst immediate size constraints and need to fix up
|
* blow the tst immediate size constraints and need to fix up
|
||||||
* arch/sh/kernel/entry-common.S.
|
* arch/sh/kernel/entry-common.S.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* work to do in syscall trace */
|
/* work to do in syscall trace */
|
||||||
#define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
|
#define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
|
||||||
_TIF_SYSCALL_AUDIT | _TIF_SECCOMP)
|
_TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
|
||||||
|
_TIF_SYSCALL_FTRACE)
|
||||||
|
|
||||||
/* work to do on any return to u-space */
|
/* work to do on any return to u-space */
|
||||||
#define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \
|
#define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \
|
||||||
_TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \
|
_TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \
|
||||||
_TIF_SINGLESTEP | _TIF_RESTORE_SIGMASK | \
|
_TIF_SINGLESTEP | _TIF_RESTORE_SIGMASK | \
|
||||||
_TIF_NOTIFY_RESUME)
|
_TIF_NOTIFY_RESUME | _TIF_SYSCALL_FTRACE)
|
||||||
|
|
||||||
/* work to do on interrupt/exception return */
|
/* work to do on interrupt/exception return */
|
||||||
#define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
|
#define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
|
||||||
|
|
|
@ -29,6 +29,7 @@ obj-$(CONFIG_IO_TRAPPED) += io_trapped.o
|
||||||
obj-$(CONFIG_KPROBES) += kprobes.o
|
obj-$(CONFIG_KPROBES) += kprobes.o
|
||||||
obj-$(CONFIG_GENERIC_GPIO) += gpio.o
|
obj-$(CONFIG_GENERIC_GPIO) += gpio.o
|
||||||
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
||||||
|
obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
|
||||||
obj-$(CONFIG_DUMP_CODE) += disassemble.o
|
obj-$(CONFIG_DUMP_CODE) += disassemble.o
|
||||||
obj-$(CONFIG_HIBERNATION) += swsusp.o
|
obj-$(CONFIG_HIBERNATION) += swsusp.o
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ ENTRY(resume_userspace)
|
||||||
nop
|
nop
|
||||||
#endif
|
#endif
|
||||||
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
|
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
|
||||||
tst #_TIF_WORK_MASK, r0
|
tst #(_TIF_WORK_MASK & 0xff), r0
|
||||||
bt/s __restore_all
|
bt/s __restore_all
|
||||||
tst #_TIF_NEED_RESCHED, r0
|
tst #_TIF_NEED_RESCHED, r0
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ work_resched:
|
||||||
#endif
|
#endif
|
||||||
!
|
!
|
||||||
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
|
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
|
||||||
tst #_TIF_WORK_MASK, r0
|
tst #(_TIF_WORK_MASK & 0xff), r0
|
||||||
bt __restore_all
|
bt __restore_all
|
||||||
bra work_pending
|
bra work_pending
|
||||||
tst #_TIF_NEED_RESCHED, r0
|
tst #_TIF_NEED_RESCHED, r0
|
||||||
|
@ -181,7 +181,7 @@ work_resched:
|
||||||
syscall_exit_work:
|
syscall_exit_work:
|
||||||
! r0: current_thread_info->flags
|
! r0: current_thread_info->flags
|
||||||
! r8: current_thread_info
|
! r8: current_thread_info
|
||||||
tst #_TIF_WORK_SYSCALL_MASK, r0
|
tst #(_TIF_WORK_SYSCALL_MASK & 0xff), r0
|
||||||
bt/s work_pending
|
bt/s work_pending
|
||||||
tst #_TIF_NEED_RESCHED, r0
|
tst #_TIF_NEED_RESCHED, r0
|
||||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||||
|
@ -331,8 +331,12 @@ ENTRY(system_call)
|
||||||
!
|
!
|
||||||
get_current_thread_info r8, r10
|
get_current_thread_info r8, r10
|
||||||
mov.l @(TI_FLAGS,r8), r8
|
mov.l @(TI_FLAGS,r8), r8
|
||||||
mov #_TIF_WORK_SYSCALL_MASK, r10
|
mov #(_TIF_WORK_SYSCALL_MASK & 0xff), r10
|
||||||
|
mov #(_TIF_WORK_SYSCALL_MASK >> 8), r9
|
||||||
tst r10, r8
|
tst r10, r8
|
||||||
|
shll8 r9
|
||||||
|
bf syscall_trace_entry
|
||||||
|
tst r9, r8
|
||||||
bf syscall_trace_entry
|
bf syscall_trace_entry
|
||||||
!
|
!
|
||||||
mov.l 2f, r8 ! Number of syscalls
|
mov.l 2f, r8 ! Number of syscalls
|
||||||
|
@ -359,7 +363,11 @@ syscall_exit:
|
||||||
!
|
!
|
||||||
get_current_thread_info r8, r0
|
get_current_thread_info r8, r0
|
||||||
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
|
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
|
||||||
tst #_TIF_ALLWORK_MASK, r0
|
tst #(_TIF_ALLWORK_MASK & 0xff), r0
|
||||||
|
mov #(_TIF_ALLWORK_MASK >> 8), r1
|
||||||
|
bf syscall_exit_work
|
||||||
|
shlr8 r0
|
||||||
|
tst r0, r1
|
||||||
bf syscall_exit_work
|
bf syscall_exit_work
|
||||||
bra __restore_all
|
bra __restore_all
|
||||||
nop
|
nop
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <asm/ftrace.h>
|
#include <asm/ftrace.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/unistd.h>
|
||||||
|
#include <trace/syscall.h>
|
||||||
|
|
||||||
static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE];
|
static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE];
|
||||||
|
|
||||||
|
@ -131,3 +133,69 @@ int __init ftrace_dyn_arch_init(void *data)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_FTRACE_SYSCALLS
|
||||||
|
|
||||||
|
extern unsigned long __start_syscalls_metadata[];
|
||||||
|
extern unsigned long __stop_syscalls_metadata[];
|
||||||
|
extern unsigned long *sys_call_table;
|
||||||
|
|
||||||
|
static struct syscall_metadata **syscalls_metadata;
|
||||||
|
|
||||||
|
static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
|
||||||
|
{
|
||||||
|
struct syscall_metadata *start;
|
||||||
|
struct syscall_metadata *stop;
|
||||||
|
char str[KSYM_SYMBOL_LEN];
|
||||||
|
|
||||||
|
|
||||||
|
start = (struct syscall_metadata *)__start_syscalls_metadata;
|
||||||
|
stop = (struct syscall_metadata *)__stop_syscalls_metadata;
|
||||||
|
kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
|
||||||
|
|
||||||
|
for ( ; start < stop; start++) {
|
||||||
|
if (start->name && !strcmp(start->name, str))
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FTRACE_SYSCALL_MAX (NR_syscalls - 1)
|
||||||
|
|
||||||
|
struct syscall_metadata *syscall_nr_to_meta(int nr)
|
||||||
|
{
|
||||||
|
if (!syscalls_metadata || nr >= FTRACE_SYSCALL_MAX || nr < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return syscalls_metadata[nr];
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_init_ftrace_syscalls(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct syscall_metadata *meta;
|
||||||
|
unsigned long **psys_syscall_table = &sys_call_table;
|
||||||
|
static atomic_t refs;
|
||||||
|
|
||||||
|
if (atomic_inc_return(&refs) != 1)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
|
||||||
|
FTRACE_SYSCALL_MAX, GFP_KERNEL);
|
||||||
|
if (!syscalls_metadata) {
|
||||||
|
WARN_ON(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < FTRACE_SYSCALL_MAX; i++) {
|
||||||
|
meta = find_syscall_meta(psys_syscall_table[i]);
|
||||||
|
syscalls_metadata[i] = meta;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Paranoid: avoid overflow */
|
||||||
|
end:
|
||||||
|
atomic_dec(&refs);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_FTRACE_SYSCALLS */
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
#include <asm/syscalls.h>
|
#include <asm/syscalls.h>
|
||||||
#include <asm/fpu.h>
|
#include <asm/fpu.h>
|
||||||
|
|
||||||
|
#include <trace/syscall.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This routine will get a word off of the process kernel stack.
|
* This routine will get a word off of the process kernel stack.
|
||||||
*/
|
*/
|
||||||
|
@ -459,6 +461,9 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
|
||||||
*/
|
*/
|
||||||
ret = -1L;
|
ret = -1L;
|
||||||
|
|
||||||
|
if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
|
||||||
|
ftrace_syscall_enter(regs);
|
||||||
|
|
||||||
if (unlikely(current->audit_context))
|
if (unlikely(current->audit_context))
|
||||||
audit_syscall_entry(audit_arch(), regs->regs[3],
|
audit_syscall_entry(audit_arch(), regs->regs[3],
|
||||||
regs->regs[4], regs->regs[5],
|
regs->regs[4], regs->regs[5],
|
||||||
|
@ -475,6 +480,9 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
|
||||||
audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
|
audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
|
||||||
regs->regs[0]);
|
regs->regs[0]);
|
||||||
|
|
||||||
|
if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
|
||||||
|
ftrace_syscall_exit(regs);
|
||||||
|
|
||||||
step = test_thread_flag(TIF_SINGLESTEP);
|
step = test_thread_flag(TIF_SINGLESTEP);
|
||||||
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
|
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
|
||||||
tracehook_report_syscall_exit(regs, step);
|
tracehook_report_syscall_exit(regs, step);
|
||||||
|
|
|
@ -72,7 +72,7 @@ ftrace_caller:
|
||||||
mov.l @r0, r0
|
mov.l @r0, r0
|
||||||
tst r0, r0
|
tst r0, r0
|
||||||
bf ftrace_stub
|
bf ftrace_stub
|
||||||
|
|
||||||
MCOUNT_ENTER()
|
MCOUNT_ENTER()
|
||||||
|
|
||||||
.globl ftrace_call
|
.globl ftrace_call
|
||||||
|
|
Loading…
Reference in a new issue