From 834904c0647b37e4f5c7118783259c53e172d267 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 26 Feb 2010 17:08:16 -0500 Subject: [PATCH] --- yaml --- r: 182313 b: refs/heads/master c: f1c7f517a5dc23bce07efa5ed55e2c074ed9d4ba h: refs/heads/master i: 182311: b75180e3bf894488c4ab036c19f982e3ecfb2e66 v: v3 --- [refs] | 2 +- trunk/Documentation/trace/ftrace-design.txt | 5 +- trunk/arch/Kconfig | 8 --- trunk/arch/s390/Kconfig | 1 - trunk/arch/s390/include/asm/ptrace.h | 13 +---- trunk/arch/s390/include/asm/syscall.h | 7 --- trunk/arch/s390/kernel/ftrace.c | 10 ++++ trunk/arch/s390/kernel/ptrace.c | 58 --------------------- trunk/arch/sh/include/asm/syscall.h | 2 - trunk/arch/sh/kernel/ftrace.c | 9 ++++ trunk/arch/sparc/include/asm/syscall.h | 7 --- trunk/arch/sparc/kernel/ftrace.c | 11 ++++ trunk/arch/x86/Kconfig | 1 - trunk/arch/x86/include/asm/syscall.h | 2 - trunk/arch/x86/kernel/ftrace.c | 10 ++++ trunk/include/linux/ftrace.h | 6 --- trunk/kernel/trace/Kconfig | 2 +- trunk/kernel/trace/trace_functions_graph.c | 52 ++++++++++++++---- trunk/kernel/trace/trace_syscalls.c | 5 -- 19 files changed, 89 insertions(+), 122 deletions(-) diff --git a/[refs] b/[refs] index 07769485ce4a..c58367f8e9ff 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6fb83029db161141d68cf019760a893d03d0682b +refs/heads/master: f1c7f517a5dc23bce07efa5ed55e2c074ed9d4ba diff --git a/trunk/Documentation/trace/ftrace-design.txt b/trunk/Documentation/trace/ftrace-design.txt index f1f81afee8a0..6a5a579126b0 100644 --- a/trunk/Documentation/trace/ftrace-design.txt +++ b/trunk/Documentation/trace/ftrace-design.txt @@ -238,10 +238,11 @@ HAVE_SYSCALL_TRACEPOINTS You need very few things to get the syscalls tracing in an arch. -- Support HAVE_ARCH_TRACEHOOK (see arch/Kconfig). - Have a NR_syscalls variable in that provides the number of syscalls supported by the arch. -- Support the TIF_SYSCALL_TRACEPOINT thread flags. +- Implement arch_syscall_addr() that resolves a syscall address from a + syscall number. +- Support the TIF_SYSCALL_TRACEPOINT thread flags - Put the trace_sys_enter() and trace_sys_exit() tracepoints calls from ptrace in the ptrace syscalls tracing path. - Tag this arch as HAVE_SYSCALL_TRACEPOINTS. diff --git a/trunk/arch/Kconfig b/trunk/arch/Kconfig index 50877ef25844..9d055b4f0585 100644 --- a/trunk/arch/Kconfig +++ b/trunk/arch/Kconfig @@ -121,14 +121,6 @@ config HAVE_DMA_ATTRS config USE_GENERIC_SMP_HELPERS bool -config HAVE_REGS_AND_STACK_ACCESS_API - bool - help - This symbol should be selected by an architecure if it supports - the API needed to access registers and stack entries from pt_regs, - declared in asm/ptrace.h - For example the kprobes-based event tracer needs this API. - config HAVE_CLK bool help diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index 2590ce20157d..c80235206c01 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -87,7 +87,6 @@ config S390 select HAVE_SYSCALL_TRACEPOINTS select HAVE_DYNAMIC_FTRACE select HAVE_FUNCTION_GRAPH_TRACER - select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_DEFAULT_NO_SPIN_MUTEXES select HAVE_OPROFILE select HAVE_KPROBES diff --git a/trunk/arch/s390/include/asm/ptrace.h b/trunk/arch/s390/include/asm/ptrace.h index dd2d913afcae..95dcf183a28d 100644 --- a/trunk/arch/s390/include/asm/ptrace.h +++ b/trunk/arch/s390/include/asm/ptrace.h @@ -492,24 +492,13 @@ struct user_regs_struct struct task_struct; extern void user_enable_single_step(struct task_struct *); extern void user_disable_single_step(struct task_struct *); -extern void show_regs(struct pt_regs * regs); #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) #define user_stack_pointer(regs)((regs)->gprs[15]) #define regs_return_value(regs)((regs)->gprs[2]) #define profile_pc(regs) instruction_pointer(regs) - -int regs_query_register_offset(const char *name); -const char *regs_query_register_name(unsigned int offset); -unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset); -unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n); - -static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) -{ - return regs->gprs[15] & PSW_ADDR_INSN; -} - +extern void show_regs(struct pt_regs * regs); #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ diff --git a/trunk/arch/s390/include/asm/syscall.h b/trunk/arch/s390/include/asm/syscall.h index 8429686951f9..e0a73d3eb837 100644 --- a/trunk/arch/s390/include/asm/syscall.h +++ b/trunk/arch/s390/include/asm/syscall.h @@ -15,13 +15,6 @@ #include #include -/* - * The syscall table always contains 32 bit pointers since we know that the - * address of the function to be called is (way) below 4GB. So the "int" - * type here is what we want [need] for both 32 bit and 64 bit systems. - */ -extern const unsigned int sys_call_table[]; - static inline long syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { diff --git a/trunk/arch/s390/kernel/ftrace.c b/trunk/arch/s390/kernel/ftrace.c index 9e69449e77ad..5a82bc68193e 100644 --- a/trunk/arch/s390/kernel/ftrace.c +++ b/trunk/arch/s390/kernel/ftrace.c @@ -200,3 +200,13 @@ unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent) return parent; } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + +#ifdef CONFIG_FTRACE_SYSCALLS + +extern unsigned int sys_call_table[]; + +unsigned long __init arch_syscall_addr(int nr) +{ + return (unsigned long)sys_call_table[nr]; +} +#endif diff --git a/trunk/arch/s390/kernel/ptrace.c b/trunk/arch/s390/kernel/ptrace.c index 33fdc5a79764..7cf464234419 100644 --- a/trunk/arch/s390/kernel/ptrace.c +++ b/trunk/arch/s390/kernel/ptrace.c @@ -992,61 +992,3 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) #endif return &user_s390_view; } - -static const char *gpr_names[NUM_GPRS] = { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", -}; - -unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset) -{ - if (offset >= NUM_GPRS) - return 0; - return regs->gprs[offset]; -} - -int regs_query_register_offset(const char *name) -{ - unsigned long offset; - - if (!name || *name != 'r') - return -EINVAL; - if (strict_strtoul(name + 1, 10, &offset)) - return -EINVAL; - if (offset >= NUM_GPRS) - return -EINVAL; - return offset; -} - -const char *regs_query_register_name(unsigned int offset) -{ - if (offset >= NUM_GPRS) - return NULL; - return gpr_names[offset]; -} - -static int regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) -{ - unsigned long ksp = kernel_stack_pointer(regs); - - return (addr & ~(THREAD_SIZE - 1)) == (ksp & ~(THREAD_SIZE - 1)); -} - -/** - * regs_get_kernel_stack_nth() - get Nth entry of the stack - * @regs:pt_regs which contains kernel stack pointer. - * @n:stack entry number. - * - * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which - * is specifined by @regs. If the @n th entry is NOT in the kernel stack, - * this returns 0. - */ -unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) -{ - unsigned long addr; - - addr = kernel_stack_pointer(regs) + n * sizeof(long); - if (!regs_within_kernel_stack(regs, addr)) - return 0; - return *(unsigned long *)addr; -} diff --git a/trunk/arch/sh/include/asm/syscall.h b/trunk/arch/sh/include/asm/syscall.h index aa7777bdc370..6a381429ee9d 100644 --- a/trunk/arch/sh/include/asm/syscall.h +++ b/trunk/arch/sh/include/asm/syscall.h @@ -1,8 +1,6 @@ #ifndef __ASM_SH_SYSCALL_H #define __ASM_SH_SYSCALL_H -extern const unsigned long sys_call_table[]; - #ifdef CONFIG_SUPERH32 # include "syscall_32.h" #else diff --git a/trunk/arch/sh/kernel/ftrace.c b/trunk/arch/sh/kernel/ftrace.c index 30e13196d35b..a48cdedc73b5 100644 --- a/trunk/arch/sh/kernel/ftrace.c +++ b/trunk/arch/sh/kernel/ftrace.c @@ -399,3 +399,12 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) } } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + +#ifdef CONFIG_FTRACE_SYSCALLS +extern unsigned long *sys_call_table; + +unsigned long __init arch_syscall_addr(int nr) +{ + return (unsigned long)sys_call_table[nr]; +} +#endif /* CONFIG_FTRACE_SYSCALLS */ diff --git a/trunk/arch/sparc/include/asm/syscall.h b/trunk/arch/sparc/include/asm/syscall.h index 025a02ad2e31..7486c605e23c 100644 --- a/trunk/arch/sparc/include/asm/syscall.h +++ b/trunk/arch/sparc/include/asm/syscall.h @@ -5,13 +5,6 @@ #include #include -/* - * The syscall table always contains 32 bit pointers since we know that the - * address of the function to be called is (way) below 4GB. So the "int" - * type here is what we want [need] for both 32 bit and 64 bit systems. - */ -extern const unsigned int sys_call_table[]; - /* The system call number is given by the user in %g1 */ static inline long syscall_get_nr(struct task_struct *task, struct pt_regs *regs) diff --git a/trunk/arch/sparc/kernel/ftrace.c b/trunk/arch/sparc/kernel/ftrace.c index 9103a56b39e8..29973daa9930 100644 --- a/trunk/arch/sparc/kernel/ftrace.c +++ b/trunk/arch/sparc/kernel/ftrace.c @@ -91,3 +91,14 @@ int __init ftrace_dyn_arch_init(void *data) return 0; } #endif + +#ifdef CONFIG_FTRACE_SYSCALLS + +extern unsigned int sys_call_table[]; + +unsigned long __init arch_syscall_addr(int nr) +{ + return (unsigned long)sys_call_table[nr]; +} + +#endif diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig index 0896008f7509..eb4092568f9e 100644 --- a/trunk/arch/x86/Kconfig +++ b/trunk/arch/x86/Kconfig @@ -45,7 +45,6 @@ config X86 select HAVE_GENERIC_DMA_COHERENT if X86_32 select HAVE_EFFICIENT_UNALIGNED_ACCESS select USER_STACKTRACE_SUPPORT - select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_DMA_API_DEBUG select HAVE_KERNEL_GZIP select HAVE_KERNEL_BZIP2 diff --git a/trunk/arch/x86/include/asm/syscall.h b/trunk/arch/x86/include/asm/syscall.h index c4a348f7bd43..8d33bc5462d1 100644 --- a/trunk/arch/x86/include/asm/syscall.h +++ b/trunk/arch/x86/include/asm/syscall.h @@ -16,8 +16,6 @@ #include #include -extern const unsigned long sys_call_table[]; - /* * Only the low 32 bits of orig_ax are meaningful, so we return int. * This importantly ignores the high bits on 64-bit, so comparisons diff --git a/trunk/arch/x86/kernel/ftrace.c b/trunk/arch/x86/kernel/ftrace.c index cd37469b54ee..605ef196fdd6 100644 --- a/trunk/arch/x86/kernel/ftrace.c +++ b/trunk/arch/x86/kernel/ftrace.c @@ -510,3 +510,13 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, } } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + +#ifdef CONFIG_FTRACE_SYSCALLS + +extern unsigned long *sys_call_table; + +unsigned long __init arch_syscall_addr(int nr) +{ + return (unsigned long)(&sys_call_table)[nr]; +} +#endif diff --git a/trunk/include/linux/ftrace.h b/trunk/include/linux/ftrace.h index 1cbb36f2759c..0b4f97d24d7f 100644 --- a/trunk/include/linux/ftrace.h +++ b/trunk/include/linux/ftrace.h @@ -511,10 +511,4 @@ static inline void trace_hw_branch_oops(void) {} #endif /* CONFIG_HW_BRANCH_TRACER */ -#ifdef CONFIG_FTRACE_SYSCALLS - -unsigned long arch_syscall_addr(int nr); - -#endif /* CONFIG_FTRACE_SYSCALLS */ - #endif /* _LINUX_FTRACE_H */ diff --git a/trunk/kernel/trace/Kconfig b/trunk/kernel/trace/Kconfig index 13e13d428cd3..e6b99b8c3d35 100644 --- a/trunk/kernel/trace/Kconfig +++ b/trunk/kernel/trace/Kconfig @@ -440,7 +440,7 @@ config BLK_DEV_IO_TRACE config KPROBE_EVENT depends on KPROBES - depends on HAVE_REGS_AND_STACK_ACCESS_API + depends on X86 bool "Enable kprobes-based dynamic events" select TRACING default y diff --git a/trunk/kernel/trace/trace_functions_graph.c b/trunk/kernel/trace/trace_functions_graph.c index 112561df2a0a..e998a824e9db 100644 --- a/trunk/kernel/trace/trace_functions_graph.c +++ b/trunk/kernel/trace/trace_functions_graph.c @@ -18,6 +18,7 @@ struct fgraph_cpu_data { pid_t last_pid; int depth; int ignore; + unsigned long enter_funcs[FTRACE_RETFUNC_DEPTH]; }; struct fgraph_data { @@ -670,15 +671,21 @@ print_graph_entry_leaf(struct trace_iterator *iter, duration = graph_ret->rettime - graph_ret->calltime; if (data) { + struct fgraph_cpu_data *cpu_data; int cpu = iter->cpu; - int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth); + + cpu_data = per_cpu_ptr(data->cpu_data, cpu); /* * Comments display at + 1 to depth. Since * this is a leaf function, keep the comments * equal to this depth. */ - *depth = call->depth - 1; + cpu_data->depth = call->depth - 1; + + /* No need to keep this function around for this depth */ + if (call->depth < FTRACE_RETFUNC_DEPTH) + cpu_data->enter_funcs[call->depth] = 0; } /* Overhead */ @@ -718,10 +725,15 @@ print_graph_entry_nested(struct trace_iterator *iter, int i; if (data) { + struct fgraph_cpu_data *cpu_data; int cpu = iter->cpu; - int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth); - *depth = call->depth; + cpu_data = per_cpu_ptr(data->cpu_data, cpu); + cpu_data->depth = call->depth; + + /* Save this function pointer to see if the exit matches */ + if (call->depth < FTRACE_RETFUNC_DEPTH) + cpu_data->enter_funcs[call->depth] = call->func; } /* No overhead */ @@ -851,18 +863,28 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, struct fgraph_data *data = iter->private; pid_t pid = ent->pid; int cpu = iter->cpu; + int func_match = 1; int ret; int i; if (data) { - int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth); + struct fgraph_cpu_data *cpu_data; + int cpu = iter->cpu; + + cpu_data = per_cpu_ptr(data->cpu_data, cpu); /* * Comments display at + 1 to depth. This is the * return from a function, we now want the comments * to display at the same level of the bracket. */ - *depth = trace->depth - 1; + cpu_data->depth = trace->depth - 1; + + if (trace->depth < FTRACE_RETFUNC_DEPTH) { + if (cpu_data->enter_funcs[trace->depth] != trace->func) + func_match = 0; + cpu_data->enter_funcs[trace->depth] = 0; + } } if (print_graph_prologue(iter, s, 0, 0)) @@ -887,9 +909,21 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, return TRACE_TYPE_PARTIAL_LINE; } - ret = trace_seq_printf(s, "}\n"); - if (!ret) - return TRACE_TYPE_PARTIAL_LINE; + /* + * If the return function does not have a matching entry, + * then the entry was lost. Instead of just printing + * the '}' and letting the user guess what function this + * belongs to, write out the function name. + */ + if (func_match) { + ret = trace_seq_printf(s, "}\n"); + if (!ret) + return TRACE_TYPE_PARTIAL_LINE; + } else { + ret = trace_seq_printf(s, "} (%ps)\n", (void *)trace->func); + if (!ret) + return TRACE_TYPE_PARTIAL_LINE; + } /* Overrun */ if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERRUN) { diff --git a/trunk/kernel/trace/trace_syscalls.c b/trunk/kernel/trace/trace_syscalls.c index a1834dda85f4..8cdda95da81a 100644 --- a/trunk/kernel/trace/trace_syscalls.c +++ b/trunk/kernel/trace/trace_syscalls.c @@ -394,11 +394,6 @@ int init_syscall_trace(struct ftrace_event_call *call) return id; } -unsigned long __init arch_syscall_addr(int nr) -{ - return (unsigned long)sys_call_table[nr]; -} - int __init init_ftrace_syscalls(void) { struct syscall_metadata *meta;