kprobes/ftrace: Have kprobes use ftrace on ftrace nops
Steven Rostedt
maintainercover kprobes/ftrace: Have kprobes use ftrace on ftrace nops
Hi All,
I started working on adding the -mfentry switch to ftrace, which allows us to remove the frame pointers requirement from function tracing as well as makes mcount (fentry) work just better.
But when I did this in another branch, I noticed that I broke kprobes in its most common usage. The attaching a probe at the beginning of a function to use get to its parameters.
So I started this branch. This branch is to have kprobes use ftrace directly when a probe is attached to a ftrace nop. Currently, kprobes will just error when that happens. With this patch set, it will hook into the ftrace infrastructure and use ftrace instead. This is more like an optimized probe as no breakpoints need to be set. A call to the function is done directly via the mcount trampoline. If ftrace pt_regs is implemented for an arch, kprobes gets this feature for free.
The first patch is just a clean up that I need to push out to get rid of the annoying compile warning about initialized variables that gcc can't tell have been initialized.
The next two patches have ftrace pass both the ftrace_ops structure and the pt_regs to the callback function that is registered with ftrace.
The last two patches have kprobes interact with ftrace and use the ftrace infrastructure instead.
I only did this for x86_64, and will do it for x86_32 and PPC64 if everyone agrees with this approach. Then I could find people to do it for other archs :)
Thanks!
-- Steve
This patch set can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace.git
rfc/kprobes/ftrace
Head SHA1: e704df971bc958c789e9dcf0b453e4c02e27887b
Steven Rostedt (5):
tracing: Clean up tb_fmt to not give faulty compile warning
ftrace: Pass ftrace_ops as third parameter to function trace callback
ftrace: Return pt_regs to function trace callback (x86_64 only so far)
kprobes: Inverse taking of module_mutex with kprobe_mutex
kprobes: Use ftrace hooks when probing ftrace nops
----
arch/x86/include/asm/ftrace.h | 42 ++++++---- arch/x86/kernel/entry_64.S | 24 +++++- include/linux/ftrace.h | 27 ++++++- include/linux/kprobes.h | 6 ++ kernel/kprobes.c | 167 ++++++++++++++++++++++++++++++++++--- kernel/trace/ftrace.c | 74 +++++++++++------ kernel/trace/trace_events.c | 3 +- kernel/trace/trace_functions.c | 10 ++- kernel/trace/trace_irqsoff.c | 3 +- kernel/trace/trace_printk.c | 19 ++-- kernel/trace/trace_sched_wakeup.c | 3 +- kernel/trace/trace_selftest.c | 20 ++++- kernel/trace/trace_stack.c | 3 +- 13 files changed, 323 insertions(+), 78 deletions(-)
Steven Rostedt
maintainerRFC PATCH 1/5 tracing: Clean up tb_fmt to not give faulty compile warning
From: Steven Rostedt <[email protected]>
gcc incorrectly states that the variable "fmt" is uninitialized when CC_OPITMIZE_FOR_SIZE is set.
Instead of just blindly setting fmt to NULL, the code is cleaned up a little to be a bit easier for humans to follow, as well as gcc to know the variables are initialized.
--- kernel/trace/trace_printk.c | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-)
kernel/trace/trace_printk.c +10 -9
@@ -59,18 +59,19 @@ void hold_module_trace_bprintk_format(const char **start, const char **end)continue ; } + fmt =NULL ; tb_fmt =kmalloc (sizeof (*tb_fmt),GFP_KERNEL ); -if (tb_fmt) +if (tb_fmt) { fmt =kmalloc (strlen (*iter) +1 ,GFP_KERNEL ); -if (tb_fmt && fmt) { -list_add_tail (&tb_fmt->list, &trace_bprintk_fmt_list); -strcpy (fmt, *iter); - tb_fmt->fmt = fmt; - *iter = tb_fmt->fmt; - }else { -kfree (tb_fmt); - *iter =NULL ; +if (fmt) { +list_add_tail (&tb_fmt->list, &trace_bprintk_fmt_list); +strcpy (fmt, *iter); + tb_fmt->fmt = fmt; + }else +kfree (tb_fmt); } + *iter = fmt; + }mutex_unlock (&btrace_mutex); }
Signature · 1 line
1.7.5.4
Steven Rostedt
maintainerRFC PATCH 2/5 ftrace: Pass ftrace_ops as third parameter to function trace
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
Currently the function trace callback receives only the ip and parent_ip of the function that it traced. It would be more powerful to also return the ops that registered the function as well. This allows the same function to act differently depending on what ftrace_ops registered it.
--- arch/x86/include/asm/ftrace.h | 4 ++ arch/x86/kernel/entry_64.S | 1 + include/linux/ftrace.h | 16 ++++++++- kernel/trace/ftrace.c | 65 ++++++++++++++++++++++--------------- kernel/trace/trace_events.c | 3 +- kernel/trace/trace_functions.c | 9 +++-- kernel/trace/trace_irqsoff.c | 3 +- kernel/trace/trace_sched_wakeup.c | 2 +- kernel/trace/trace_selftest.c | 15 ++++++--- kernel/trace/trace_stack.c | 2 +- 10 files changed, 80 insertions(+), 40 deletions(-)
arch/x86/include/asm/ftrace.h +4 -0
@@ -32,6 +32,10 @@#define MCOUNT_ADDR ((long)(mcount))#define MCOUNT_INSN_SIZE 5/* sizeof mcount call */ +#if defined(CONFIG_DYNAMIC_FTRACE ) && defined(CONFIG_X86_64 ) +#define ARCH_SUPPORTS_FTRACE_OPS 1 +#endif +#ifndef __ASSEMBLY__extern void mcount (void );
arch/x86/kernel/entry_64.S +1 -0
@@ -77,6 +77,7 @@ ENTRY(ftrace_caller) MCOUNT_SAVE_FRAME + leaq function_trace_op, %rdx movq 0x38(%rsp), %rdi movq 8(%rbp), %rsi subq $MCOUNT_INSN_SIZE, %rdi
include/linux/ftrace.h +14 -2
@@ -19,6 +19,15 @@#include <asm/ftrace.h> +/* +* If the arch supports passing the variable contents of +* function_trace_op as the third parameter back from the +* mcount call, then the arch should define this as 1. +*/ +#ifndef ARCH_SUPPORTS_FTRACE_OPS +#define ARCH_SUPPORTS_FTRACE_OPS 0 +#endif +struct ftrace_hash ;#ifdef CONFIG_FUNCTION_TRACER
@@ -29,7 +38,10 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); -typedef void (*ftrace_func_t )(unsigned long ip,unsigned long parent_ip); +struct ftrace_ops ; + +typedef void (*ftrace_func_t )(unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op);enum {FTRACE_OPS_FL_ENABLED =1 <<0 ,
@@ -97,7 +109,7 @@ int register_ftrace_function(struct ftrace_ops *ops);int unregister_ftrace_function (struct ftrace_ops *ops);void clear_ftrace_function (void ); -extern void ftrace_stub (unsigned long a0,unsigned long a1); +extern void ftrace_stub (unsigned long a0,unsigned long a1,struct ftrace_ops *op);#else /* !CONFIG_FUNCTION_TRACER */ /*
kernel/trace/ftrace.c +39 -26
150 lines not on this page · raw message
kernel/trace/trace_events.c +2 -1
@@ -1673,7 +1673,8 @@ static __init void event_trace_self_tests(void) static DEFINE_PER_CPU(atomic_t, ftrace_test_event_disable);static void -function_test_events_call (unsigned long ip,unsigned long parent_ip) +function_test_events_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op) {struct ring_buffer_event *event;struct ring_buffer *buffer;
kernel/trace/trace_functions.c +6 -3
@@ -48,7 +48,8 @@ static void function_trace_start(struct trace_array *tr) }static void -function_trace_call_preempt_only (unsigned long ip,unsigned long parent_ip) +function_trace_call_preempt_only (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
@@ -75,7 +76,8 @@ function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip) }static void -function_trace_call (unsigned long ip,unsigned long parent_ip) +function_trace_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
@@ -106,7 +108,8 @@ function_trace_call(unsigned long ip, unsigned long parent_ip) }static void -function_stack_trace_call (unsigned long ip,unsigned long parent_ip) +function_stack_trace_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
kernel/trace/trace_irqsoff.c +2 -1
@@ -136,7 +136,8 @@ static int func_prolog_dec(struct trace_array *tr,* irqsoff uses its own tracer function to keep the overhead down: */ static void -irqsoff_tracer_call (unsigned long ip,unsigned long parent_ip) +irqsoff_tracer_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op) {struct trace_array *tr = irqsoff_trace;struct trace_array_cpu *data;
kernel/trace/trace_sched_wakeup.c +1 -1
@@ -108,7 +108,7 @@ out_enable:* wakeup uses its own tracer function to keep the overhead down: */ static void -wakeup_tracer_call (unsigned long ip,unsigned long parent_ip) +wakeup_tracer_call (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op) {struct trace_array *tr = wakeup_trace;struct trace_array_cpu *data;
kernel/trace/trace_selftest.c +10 -5
@@ -103,35 +103,40 @@ static inline void warn_failed_init_tracer(struct tracer *trace, int init_ret)static int trace_selftest_test_probe1_cnt;static void trace_selftest_test_probe1_func (unsigned long ip, -unsigned long pip) +unsigned long pip, +struct ftrace_ops *op) { trace_selftest_test_probe1_cnt++; }static int trace_selftest_test_probe2_cnt;static void trace_selftest_test_probe2_func (unsigned long ip, -unsigned long pip) +unsigned long pip, +struct ftrace_ops *op) { trace_selftest_test_probe2_cnt++; }static int trace_selftest_test_probe3_cnt;static void trace_selftest_test_probe3_func (unsigned long ip, -unsigned long pip) +unsigned long pip, +struct ftrace_ops *op) { trace_selftest_test_probe3_cnt++; }static int trace_selftest_test_global_cnt;static void trace_selftest_test_global_func (unsigned long ip, -unsigned long pip) +unsigned long pip, +struct ftrace_ops *op) { trace_selftest_test_global_cnt++; }static int trace_selftest_test_dyn_cnt;static void trace_selftest_test_dyn_func (unsigned long ip, -unsigned long pip) +unsigned long pip, +struct ftrace_ops *op) { trace_selftest_test_dyn_cnt++; }
kernel/trace/trace_stack.c +1 -1
@@ -108,7 +108,7 @@ static inline void check_stack(void) }static void -stack_trace_call (unsigned long ip,unsigned long parent_ip) +stack_trace_call (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op) {int cpu;
Signature · 1 line
1.7.5.4
Steven Rostedt
maintainerRFC PATCH 3/5 ftrace: Return pt_regs to function trace callback (x86_64 only so
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
Return as the 4th paramater to the function tracer callback the pt_regs.
So far this is only supported by x86_64. The ftrace_ops flag FTRACE_OPS_FL_SAVE_REGS is added to tell the arch to save all regs to the pt_regs, otherwise a minimum is just passed back (the same regs that is saved by mcount itself).
--- arch/x86/include/asm/ftrace.h | 38 ++++++++++++++++++++---------------- arch/x86/kernel/entry_64.S | 23 +++++++++++++++++++++- include/linux/ftrace.h | 15 ++++++++++++- kernel/trace/ftrace.c | 29 ++++++++++++++++++--------- kernel/trace/trace_events.c | 2 +- kernel/trace/trace_functions.c | 7 +++-- kernel/trace/trace_irqsoff.c | 2 +- kernel/trace/trace_sched_wakeup.c | 3 +- kernel/trace/trace_selftest.c | 15 +++++++++---- kernel/trace/trace_stack.c | 3 +- 10 files changed, 95 insertions(+), 42 deletions(-)
arch/x86/include/asm/ftrace.h +21 -17
@@ -4,26 +4,29 @@#ifdef __ASSEMBLY__ .macro MCOUNT_SAVE_FRAME - /* taken from glibc */ - subq $0x38, %rsp - movq %rax, (%rsp) - movq %rcx, 8(%rsp) - movq %rdx, 16(%rsp) - movq %rsi, 24(%rsp) - movq %rdi, 32(%rsp) - movq %r8, 40(%rsp) - movq %r9, 48(%rsp) +/* +* We add enough stack to save all regs, +* and we what we need in the location of pt_regs. + */ + subq $ORIG_RAX, %rsp + movq %rax, RAX(%rsp) + movq %rcx, RCX(%rsp) + movq %rdx, RDX(%rsp) + movq %rsi, RSI(%rsp) + movq %rdi, RDI(%rsp) + movq %r8, R8(%rsp) + movq %r9, R9(%rsp) .endm .macro MCOUNT_RESTORE_FRAME - movq 48(%rsp), %r9 - movq 40(%rsp), %r8 - movq 32(%rsp), %rdi - movq 24(%rsp), %rsi - movq 16(%rsp), %rdx - movq 8(%rsp), %rcx - movq (%rsp), %rax - addq $0x38, %rsp + movq R9(%rsp), %r9 + movq R8(%rsp), %r8 + movq RDI(%rsp), %rdi + movq RSI(%rsp), %rsi + movq RDX(%rsp), %rdx + movq RCX(%rsp), %rcx + movq RAX(%rsp), %rax + addq $ORIG_RAX, %rsp .endm #endif
@@ -34,6 +37,7 @@#if defined(CONFIG_DYNAMIC_FTRACE ) && defined(CONFIG_X86_64 )#define ARCH_SUPPORTS_FTRACE_OPS 1 +#define ARCH_SUPPORTS_FTRACE_SAVE_REGS 1#endif #ifndef __ASSEMBLY__
arch/x86/kernel/entry_64.S +22 -1
@@ -78,7 +78,16 @@ ENTRY(ftrace_caller) MCOUNT_SAVE_FRAME leaq function_trace_op, %rdx - movq 0x38(%rsp), %rdi + + cmpl $0, ftrace_save_regs + jne save_all_regs + +call_func: + + /* regs go into 4th parameter */ + leaq (%rsp), %rcx + + movq ORIG_RAX(%rsp), %rdi movq 8(%rbp), %rsi subq $MCOUNT_INSN_SIZE, %rdi
@@ -96,6 +105,18 @@ GLOBAL(ftrace_stub) retq END(ftrace_caller) +save_all_regs: + /* Save the rest of pt_regs */ + movq %r15, R15(%rsp) + movq %r14, R14(%rsp) + movq %r13, R13(%rsp) + movq %r12, R12(%rsp) + movq %r10, R10(%rsp) + movq %rbp, RBP(%rsp) + movq %rbx, RBX(%rsp) + jmp call_func + + #else /* ! CONFIG_DYNAMIC_FTRACE */ ENTRY(mcount) cmpl $0, function_trace_stop
include/linux/ftrace.h +13 -2
@@ -11,6 +11,7 @@#include <linux/linkage.h> #include <linux/bitops.h> #include <linux/module.h> +#include <linux/ptrace.h> #include <linux/ktime.h> #include <linux/sched.h> #include <linux/types.h>
@@ -28,6 +29,14 @@#define ARCH_SUPPORTS_FTRACE_OPS 0#endif +/* +* If the arch supports saving the regs to the ftrace_ops +* then it should set this to 1. +*/ +#ifndef ARCH_SUPPORTS_FTRACE_SAVE_REGS +#define ARCH_SUPPORTS_FTRACE_SAVE_REGS 0 +#endif +struct ftrace_hash ;#ifdef CONFIG_FUNCTION_TRACER
@@ -41,12 +50,13 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,struct ftrace_ops ;typedef void (*ftrace_func_t )(unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op); +struct ftrace_ops *op,struct pt_regs *pt_regs);enum {FTRACE_OPS_FL_ENABLED =1 <<0 ,FTRACE_OPS_FL_GLOBAL =1 <<1 ,FTRACE_OPS_FL_DYNAMIC =1 <<2 , +FTRACE_OPS_FL_SAVE_REGS =1 <<3 , };struct ftrace_ops {
@@ -109,7 +119,8 @@ int register_ftrace_function(struct ftrace_ops *ops);int unregister_ftrace_function (struct ftrace_ops *ops);void clear_ftrace_function (void ); -extern void ftrace_stub (unsigned long a0,unsigned long a1,struct ftrace_ops *op); +extern void ftrace_stub (unsigned long a0,unsigned long a1, +struct ftrace_ops *op,struct pt_regs *pt_regs);#else /* !CONFIG_FUNCTION_TRACER */ /*
kernel/trace/ftrace.c +19 -10
@@ -74,6 +74,9 @@ int function_trace_stop __read_mostly;/* Current function tracing op */ struct ftrace_ops *function_trace_op__read_mostly = &ftrace_list_end; +/* If the arch supports it, return pt_regs to caller */ +int ftrace_save_regs__read_mostly ; +/* List for set_ftrace_pid's pids. */ LIST_HEAD (ftrace_pids);struct ftrace_pid {
@@ -98,7 +101,7 @@ ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;static struct ftrace_ops global_ops;static void ftrace_ops_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op); +struct ftrace_ops *op,struct pt_regs *pt_regs);/* * Traverse the ftrace_global_list, invoking all entries. The reason that we
@@ -111,7 +114,7 @@ static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,*/ static void ftrace_global_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {if (unlikely (trace_recursion_test (TRACE_GLOBAL_BIT )))return ;
@@ -119,19 +122,19 @@ ftrace_global_list_func(unsigned long ip, unsigned long parent_ip,trace_recursion_set (TRACE_GLOBAL_BIT ); op =rcu_dereference_raw (ftrace_global_list);/*see above*/ while (op != &ftrace_list_end) { - op->func (ip, parent_ip, op); + op->func (ip, parent_ip, op, pt_regs); op =rcu_dereference_raw (op->next);/*see above*/ };trace_recursion_clear (TRACE_GLOBAL_BIT ); }static void ftrace_pid_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {if (!test_tsk_trace_trace (current))return ; -ftrace_pid_function (ip, parent_ip, op); +ftrace_pid_function (ip, parent_ip, op, pt_regs); }static void set_ftrace_pid_function (ftrace_func_t func)
@@ -162,12 +165,12 @@ void clear_ftrace_function(void)* mcount call site, we need to do it from C. */ static void ftrace_test_stop_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {if (function_trace_stop)return ; -__ftrace_trace_function (ip, parent_ip, op); +__ftrace_trace_function (ip, parent_ip, op, pt_regs); }#endif
@@ -285,6 +288,9 @@ static int __register_ftrace_function(struct ftrace_ops *ops)if (!core_kernel_data ((unsigned long )ops)) ops->flags |=FTRACE_OPS_FL_DYNAMIC ; +if (ops->flags &FTRACE_OPS_FL_SAVE_REGS ) + ftrace_save_regs++; +if (ops->flags &FTRACE_OPS_FL_GLOBAL ) {int first = ftrace_global_list == &ftrace_list_end;add_ftrace_ops (&ftrace_global_list, ops);
@@ -313,6 +319,9 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)if (FTRACE_WARN_ON (ops == &global_ops))return -EINVAL ; +if (ops->flags &FTRACE_OPS_FL_SAVE_REGS ) + ftrace_save_regs--; +if (ops->flags &FTRACE_OPS_FL_GLOBAL ) { ret =remove_ftrace_ops (&ftrace_global_list, ops);if (!ret && ftrace_global_list == &ftrace_list_end)
@@ -2527,7 +2536,7 @@ static int __init ftrace_mod_cmd_init(void)device_initcall (ftrace_mod_cmd_init);static void function_trace_probe_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct ftrace_func_probe *entry;struct hlist_head *hhd;
@@ -3575,7 +3584,7 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)static void ftrace_ops_list_func (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {if (unlikely (trace_recursion_test (TRACE_INTERNAL_BIT )))return ;
@@ -3589,7 +3598,7 @@ ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, op =rcu_dereference_raw (ftrace_ops_list);while (op != &ftrace_list_end) {if (ftrace_ops_test (op, ip)) - op->func (ip, parent_ip, op); + op->func (ip, parent_ip, op, pt_regs); op =rcu_dereference_raw (op->next); };preempt_enable_notrace ();
kernel/trace/trace_events.c +1 -1
@@ -1674,7 +1674,7 @@ static DEFINE_PER_CPU(atomic_t, ftrace_test_event_disable);static void function_test_events_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct ring_buffer_event *event;struct ring_buffer *buffer;
kernel/trace/trace_functions.c +4 -3
@@ -49,7 +49,7 @@ static void function_trace_start(struct trace_array *tr)static void function_trace_call_preempt_only (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
@@ -77,7 +77,8 @@ function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip,static void function_trace_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) + {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
@@ -109,7 +110,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,static void function_stack_trace_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = func_trace;struct trace_array_cpu *data;
kernel/trace/trace_irqsoff.c +1 -1
@@ -137,7 +137,7 @@ static int func_prolog_dec(struct trace_array *tr,*/ static void irqsoff_tracer_call (unsigned long ip,unsigned long parent_ip, -struct ftrace_ops *op) +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = irqsoff_trace;struct trace_array_cpu *data;
kernel/trace/trace_sched_wakeup.c +2 -1
@@ -108,7 +108,8 @@ out_enable:* wakeup uses its own tracer function to keep the overhead down: */ static void -wakeup_tracer_call (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op) +wakeup_tracer_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) {struct trace_array *tr = wakeup_trace;struct trace_array_cpu *data;
kernel/trace/trace_selftest.c +10 -5
@@ -104,7 +104,8 @@ static inline void warn_failed_init_tracer(struct tracer *trace, int init_ret)static int trace_selftest_test_probe1_cnt;static void trace_selftest_test_probe1_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_probe1_cnt++; }
@@ -112,7 +113,8 @@ static void trace_selftest_test_probe1_func(unsigned long ip,static int trace_selftest_test_probe2_cnt;static void trace_selftest_test_probe2_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_probe2_cnt++; }
@@ -120,7 +122,8 @@ static void trace_selftest_test_probe2_func(unsigned long ip,static int trace_selftest_test_probe3_cnt;static void trace_selftest_test_probe3_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_probe3_cnt++; }
@@ -128,7 +131,8 @@ static void trace_selftest_test_probe3_func(unsigned long ip,static int trace_selftest_test_global_cnt;static void trace_selftest_test_global_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_global_cnt++; }
@@ -136,7 +140,8 @@ static void trace_selftest_test_global_func(unsigned long ip,static int trace_selftest_test_dyn_cnt;static void trace_selftest_test_dyn_func (unsigned long ip,unsigned long pip, -struct ftrace_ops *op) +struct ftrace_ops *op, +struct pt_regs *pt_regs) { trace_selftest_test_dyn_cnt++; }
kernel/trace/trace_stack.c +2 -1
@@ -108,7 +108,8 @@ static inline void check_stack(void) }static void -stack_trace_call (unsigned long ip,unsigned long parent_ip,struct ftrace_ops *op) +stack_trace_call (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) {int cpu;
Signature · 1 line
1.7.5.4
Re: [PATCH 3/5][RFC] ftrace: Return pt_regs to function trace callback (x86_64 only so
Quoted 8 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Return as the 4th paramater to the function tracer callback the
pt_regs.So far this is only supported by
x86_64. Theftrace_opsflagFTRACE_OPS_FL_SAVE_REGSis added to tell the arch to save all regs to thept_regs, otherwise a minimum is just passed back (the same regs that is saved by mcount itself).
I guess it will be a bit hard to port this on x86-32, because on x86-32, the top of stack address in pt_regs is the address of sp member (e.g. &(pt_regs->sp)). I mean that when mcount-entry calls ftrace_caller, it pushes an address of the next instruction of mcount-entry on the top of stack.
In that case, &(pt_regs->sp) points the entry which stores the address, instead of the return address of probed function.
e.g. with kprobes (on x86-32):
[ <bx> ] <- pt_regs [ ... ] [ <cs> ] [<flags> ] [ret-addr] <- &(pt_regs.sp) [ arg1 ] [ arg2 ]
with this method:
[ <bx> ] <- pt_regs [ ... ] [ <cs> ] [<flags> ] [mcount-ret] <- &(pt_regs.sp) [ret-addr] [ arg1 ] [ arg2 ]
I think this is hard to solve without a tricky hack.
For example, on x86-32, MCOUNT_FRAME_SAVE saves flags on the entry which will be <cs> and it saves mcount-ret to local stack and moves flags to next entry.
<save-frame>
pushf # save flags on CS(%esp)
subl $12, %esp # skip ip, orig_ax and gs
pushl %fs
pushl %es
...
pushl %ebx
movl 56(%esp), %ebx # load mcount-ret address
movl 52(%esp), %ebp # load flags
movl %ebp, 56(%esp) # store flags
call function (ebx is callee save)
<restore-frame>
movl 56(%esp), %ebp # load flags
movl %ebp, 52(%esp) # store flags
movl %ebx, 56(%esp) # load mcount-ret address
...
popf
ret
Hmm?
arch/x86/kernel/entry_64.S ENTRY(ftrace_caller)
Quoted 78 lines
Signed-off-by Steven Rostedt <[email protected]>--- arch/x86/include/asm/ftrace.h | 38 ++++++++++++++++++++---------------- arch/x86/kernel/entry_64.S | 23 +++++++++++++++++++++- include/linux/ftrace.h | 15 ++++++++++++- kernel/trace/ftrace.c | 29 ++++++++++++++++++--------- kernel/trace/trace_events.c | 2 +- kernel/trace/trace_functions.c | 7 +++-- kernel/trace/trace_irqsoff.c | 2 +- kernel/trace/trace_sched_wakeup.c | 3 +- kernel/trace/trace_selftest.c | 15 +++++++++---- kernel/trace/trace_stack.c | 3 +- 10 files changed, 95 insertions(+), 42 deletions(-)arch/x86/include/asm/ftrace.h +21
-17@@ -4,26 +4,29 @@#ifdef __ASSEMBLY__ .macro MCOUNT_SAVE_FRAME - /* taken from glibc */ - subq $0x38, %rsp - movq %rax, (%rsp) - movq %rcx, 8(%rsp) - movq %rdx, 16(%rsp) - movq %rsi, 24(%rsp) - movq %rdi, 32(%rsp) - movq %r8, 40(%rsp) - movq %r9, 48(%rsp) +/* +* We add enough stack to save all regs, +* and we what we need in the location of pt_regs. + */ + subq $ORIG_RAX, %rsp + movq %rax, RAX(%rsp) + movq %rcx, RCX(%rsp) + movq %rdx, RDX(%rsp) + movq %rsi, RSI(%rsp) + movq %rdi, RDI(%rsp) + movq %r8, R8(%rsp) + movq %r9, R9(%rsp) .endm .macro MCOUNT_RESTORE_FRAME - movq 48(%rsp), %r9 - movq 40(%rsp), %r8 - movq 32(%rsp), %rdi - movq 24(%rsp), %rsi - movq 16(%rsp), %rdx - movq 8(%rsp), %rcx - movq (%rsp), %rax - addq $0x38, %rsp + movq R9(%rsp), %r9 + movq R8(%rsp), %r8 + movq RDI(%rsp), %rdi + movq RSI(%rsp), %rsi + movq RDX(%rsp), %rdx + movq RCX(%rsp), %rcx + movq RAX(%rsp), %rax + addq $ORIG_RAX, %rsp .endm #endif@@ -34,6 +37,7 @@#if defined(CONFIG_DYNAMIC_FTRACE ) && defined(CONFIG_X86_64 )#define ARCH_SUPPORTS_FTRACE_OPS 1 +#define ARCH_SUPPORTS_FTRACE_SAVE_REGS 1#endif #ifndef __ASSEMBLY__arch/x86/kernel/entry_64.S +0
-0@@ -78,7 +78,16 @@ ENTRY(ftrace_caller)
I can see below code before save frame.
cmpl $0, function_trace_stop
jne ftrace_stub
Please pushf before comparing it. :)
Sometimes, the value of eflags is worth to watch.
I know that SF/ZF will be never used between
function call, so it is OK if the eflags is saved
in MCOUNT_SAVE_FRAME.
Quoted 21 lines
arch/x86/kernel/entry_64.S +10
-1MCOUNT_SAVE_FRAME leaq function_trace_op, %rdx - movq 0x38(%rsp), %rdi + + cmpl $0, ftrace_save_regs + jne save_all_regs + +call_func: + + /* regs go into 4th parameter */ + leaq (%rsp), %rcx + + movq ORIG_RAX(%rsp), %rdi movq 8(%rbp), %rsi subq $MCOUNT_INSN_SIZE, %rdi@@ -96,6 +105,18 @@ GLOBAL(ftrace_stub) retq END(ftrace_caller)
arch/x86/kernel/entry_64.S GLOBAL(ftrace_stub) · line 117
Quoted 10 lines
arch/x86/kernel/entry_64.S +10
-0+save_all_regs: + /* Save the rest of pt_regs */ + movq %r15, R15(%rsp) + movq %r14, R14(%rsp) + movq %r13, R13(%rsp) + movq %r12, R12(%rsp) + movq %r10, R10(%rsp) + movq %rbp, RBP(%rsp) + movq %rbx, RBX(%rsp) + jmp call_func
At least, pt_regs.sp must be saved for accessing
vars on stack.
arch/x86/kernel/entry_64.S GLOBAL(ftrace_stub) · line 122
Quoted 5 lines
arch/x86/kernel/entry_64.S +2
-0+ + #else /* ! CONFIG_DYNAMIC_FTRACE */ ENTRY(mcount) cmpl $0, function_trace_stop
You also need to restore the rest of pt_regs ifftrace_save_regs is true.
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerRe: [PATCH 3/5][RFC] ftrace: Return pt_regs to function trace callback (x86_64 only so
Quoted 10 lines · Masami Hiramatsu
Quoted 8 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Return as the 4th paramater to the function tracer callback the
pt_regs.So far this is only supported by
x86_64. Theftrace_opsflagFTRACE_OPS_FL_SAVE_REGSis added to tell the arch to save all regs to thept_regs, otherwise a minimum is just passed back (the same regs that is saved by mcount itself).
Quoted 7 lines
I guess it will be a bit hard to port this on x86-32, because on x86-32, the top of stack address in
pt_regsis the address of sp member (e.g. &(pt_regs->sp)). I mean that when mcount-entry callsftrace_caller, it pushes an address of the next instruction of mcount-entry on the top of stack.
In that case, &(pt_regs->sp) points the entry which stores the address, instead of the return address of probed function.
I'm a little confused here. What is needed by kprobes handlers?
It should be no problem saving the sp member onto pt_regs of the time mcount was called, and simulate the probe as if it was put on the nop.
Quoted 22 lines
e.g. with kprobes (on x86-32):
[ <bx> ] <- pt_regs [ ... ] [ <cs> ] [<flags> ] [ret-addr] <- &(pt_regs.sp) [ arg1 ] [ arg2 ]with this method:
[ <bx> ] <- pt_regs [ ... ] [ <cs> ] [<flags> ] [mcount-ret] <- &(pt_regs.sp) [ret-addr] [ arg1 ] [ arg2 ]
Quoted 1 line
I think this is hard to solve without a tricky hack.
Is this for handling kretprobes? With mcount, we shouldn't be doing that because mcount is not the place that kretprobes should be doing this. When we add __fentry__, the arch code will be different to handle that and it shouldn't be too hard to make that work with kretprobes.
Quoted 5 lines
For example, on x86-32,
MCOUNT_FRAME_SAVEsaves flags on the entry which will be <cs> and it saves mcount-ret to local stack and moves flags to next entry.
Quoted 10 lines
<save-frame>
pushf # save flags on CS(%esp)
subl $12, %esp # skip ip,orig_axand gs
pushl %fs
pushl %es
...
pushl %ebx
movl 56(%esp), %ebx # load mcount-ret address
movl 52(%esp), %ebp # load flags
movl %ebp, 56(%esp) # store flags
Nope we don't do anything like this. I've already got x86_32 working (but maybe it needs more for pt_regs->sp) but why is pushf needed?
-- Steve
Quoted 149 lines
call function (ebx is callee save)
<restore-frame>
movl 56(%esp), %ebp # load flags
movl %ebp, 52(%esp) # store flags
movl %ebx, 56(%esp) # load mcount-ret address
...
popf
retHmm?
arch/x86/kernel/entry_64.S ENTRY(ftrace_caller)
Quoted 78 lines
Signed-off-by Steven Rostedt <[email protected]>--- arch/x86/include/asm/ftrace.h | 38 ++++++++++++++++++++---------------- arch/x86/kernel/entry_64.S | 23 +++++++++++++++++++++- include/linux/ftrace.h | 15 ++++++++++++- kernel/trace/ftrace.c | 29 ++++++++++++++++++--------- kernel/trace/trace_events.c | 2 +- kernel/trace/trace_functions.c | 7 +++-- kernel/trace/trace_irqsoff.c | 2 +- kernel/trace/trace_sched_wakeup.c | 3 +- kernel/trace/trace_selftest.c | 15 +++++++++---- kernel/trace/trace_stack.c | 3 +- 10 files changed, 95 insertions(+), 42 deletions(-)arch/x86/include/asm/ftrace.h +21
-17@@ -4,26 +4,29 @@#ifdef __ASSEMBLY__ .macro MCOUNT_SAVE_FRAME - /* taken from glibc */ - subq $0x38, %rsp - movq %rax, (%rsp) - movq %rcx, 8(%rsp) - movq %rdx, 16(%rsp) - movq %rsi, 24(%rsp) - movq %rdi, 32(%rsp) - movq %r8, 40(%rsp) - movq %r9, 48(%rsp) +/* +* We add enough stack to save all regs, +* and we what we need in the location of pt_regs. + */ + subq $ORIG_RAX, %rsp + movq %rax, RAX(%rsp) + movq %rcx, RCX(%rsp) + movq %rdx, RDX(%rsp) + movq %rsi, RSI(%rsp) + movq %rdi, RDI(%rsp) + movq %r8, R8(%rsp) + movq %r9, R9(%rsp) .endm .macro MCOUNT_RESTORE_FRAME - movq 48(%rsp), %r9 - movq 40(%rsp), %r8 - movq 32(%rsp), %rdi - movq 24(%rsp), %rsi - movq 16(%rsp), %rdx - movq 8(%rsp), %rcx - movq (%rsp), %rax - addq $0x38, %rsp + movq R9(%rsp), %r9 + movq R8(%rsp), %r8 + movq RDI(%rsp), %rdi + movq RSI(%rsp), %rsi + movq RDX(%rsp), %rdx + movq RCX(%rsp), %rcx + movq RAX(%rsp), %rax + addq $ORIG_RAX, %rsp .endm #endif@@ -34,6 +37,7 @@#if defined(CONFIG_DYNAMIC_FTRACE ) && defined(CONFIG_X86_64 )#define ARCH_SUPPORTS_FTRACE_OPS 1 +#define ARCH_SUPPORTS_FTRACE_SAVE_REGS 1#endif #ifndef __ASSEMBLY__arch/x86/kernel/entry_64.S +0
-0@@ -78,7 +78,16 @@ ENTRY(ftrace_caller)I can see below code before save frame.
cmpl $0,
function_trace_stop
jneftrace_stubPlease pushf before comparing it. :)
Sometimes, the value of eflags is worth to watch.
I know that SF/ZF will be never used between
function call, so it is OK if the eflags is saved
inMCOUNT_SAVE_FRAME.Quoted 21 lines
arch/x86/kernel/entry_64.S +10
-1MCOUNT_SAVE_FRAME leaq function_trace_op, %rdx - movq 0x38(%rsp), %rdi + + cmpl $0, ftrace_save_regs + jne save_all_regs + +call_func: + + /* regs go into 4th parameter */ + leaq (%rsp), %rcx + + movq ORIG_RAX(%rsp), %rdi movq 8(%rbp), %rsi subq $MCOUNT_INSN_SIZE, %rdi@@ -96,6 +105,18 @@ GLOBAL(ftrace_stub) retq END(ftrace_caller)arch/x86/kernel/entry_64.S GLOBAL(ftrace_stub) · line 117
Quoted 10 lines
arch/x86/kernel/entry_64.S +10
-0+save_all_regs: + /* Save the rest of pt_regs */ + movq %r15, R15(%rsp) + movq %r14, R14(%rsp) + movq %r13, R13(%rsp) + movq %r12, R12(%rsp) + movq %r10, R10(%rsp) + movq %rbp, RBP(%rsp) + movq %rbx, RBX(%rsp) + jmp call_funcAt least, pt_regs.sp must be saved for accessing
vars on stack.arch/x86/kernel/entry_64.S GLOBAL(ftrace_stub) · line 122
Quoted 5 lines
arch/x86/kernel/entry_64.S +2
-0+ + #else /* ! CONFIG_DYNAMIC_FTRACE */ ENTRY(mcount) cmpl $0, function_trace_stopYou also need to restore the rest of
pt_regsifftrace_save_regsis true.Thank you,
Re: [PATCH 3/5][RFC] ftrace: Return pt_regs to function trace callback (x86_64 only so
Quoted 19 lines · Steven Rostedt
Quoted 10 lines · Masami Hiramatsu
Quoted 8 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Return as the 4th paramater to the function tracer callback the
pt_regs.So far this is only supported by
x86_64. Theftrace_opsflagFTRACE_OPS_FL_SAVE_REGSis added to tell the arch to save all regs to thept_regs, otherwise a minimum is just passed back (the same regs that is saved by mcount itself).Quoted 7 lines
I guess it will be a bit hard to port this on x86-32, because on x86-32, the top of stack address in
pt_regsis the address of sp member (e.g. &(pt_regs->sp)). I mean that when mcount-entry callsftrace_caller, it pushes an address of the next instruction of mcount-entry on the top of stack.
In that case, &(pt_regs->sp) points the entry which stores the address, instead of the return address of probed function.
Quoted 1 line
I'm a little confused here. What is needed by kprobes handlers?
pt_regs, which is same as what the breakpoint interrupt generates. This means that all members of pt_regs should be filled (except ss) as interrupt handler does.
Quoted 2 lines
It should be no problem saving the sp member onto
pt_regsof the time mcount was called, and simulate the probe as if it was put on the nop.
OK.
Quoted 23 lines
Quoted 23 lines
e.g. with kprobes (on x86-32):
[ <bx> ] <- pt_regs [ ... ] [ <cs> ] [<flags> ] [ret-addr] <- &(pt_regs.sp) [ arg1 ] [ arg2 ]with this method:
[ <bx> ] <- pt_regs [ ... ] [ <cs> ] [<flags> ] [mcount-ret] <- &(pt_regs.sp) [ret-addr] [ arg1 ] [ arg2 ]
Quoted 4 lines
Quoted 1 line
I think this is hard to solve without a tricky hack.
Is this for handling kretprobes? With mcount, we shouldn't be doing that because mcount is not the place that kretprobes should be doing this.
Yeah, I know, but if kprobe works on mcount with --fentry *transparently*, it should support kretprobes.
Moreover, if we'd like to access args on the stack, sp should be able to be handled as breakpoint-based kprobes. and that has to be done for dynamic- events on x86-32.
Quoted 19 lines
When we add
__fentry__, the arch code will be different to handle that and it shouldn't be too hard to make that work with kretprobes.Quoted 5 lines
For example, on x86-32,
MCOUNT_FRAME_SAVEsaves flags on the entry which will be <cs> and it saves mcount-ret to local stack and moves flags to next entry.Quoted 10 lines
<save-frame>
pushf # save flags on CS(%esp)
subl $12, %esp # skip ip,orig_axand gs
pushl %fs
pushl %es
...
pushl %ebx
movl 56(%esp), %ebx # load mcount-ret address
movl 52(%esp), %ebp # load flags
movl %ebp, 56(%esp) # store flags
Quoted 2 lines
Nope we don't do anything like this. I've already got
x86_32working (but maybe it needs more forpt_regs->sp) but why is pushf needed?
as I said below (inlined comment), e.g. someone who wanna chase IF, he needs eflags.
Please note, kprobes is the function which basically provides a breakpoint handler in the kernel. Users expect that. So all registers should be provided as breakpoint interrupt does. That's what I said "transparently".
Quoted 153 lines
-- Steve
Quoted 149 lines
call function (ebx is callee save)
<restore-frame>
movl 56(%esp), %ebp # load flags
movl %ebp, 52(%esp) # store flags
movl %ebx, 56(%esp) # load mcount-ret address
...
popf
retHmm?
arch/x86/kernel/entry_64.S ENTRY(ftrace_caller)
Quoted 78 lines
Signed-off-by Steven Rostedt <[email protected]>--- arch/x86/include/asm/ftrace.h | 38 ++++++++++++++++++++---------------- arch/x86/kernel/entry_64.S | 23 +++++++++++++++++++++- include/linux/ftrace.h | 15 ++++++++++++- kernel/trace/ftrace.c | 29 ++++++++++++++++++--------- kernel/trace/trace_events.c | 2 +- kernel/trace/trace_functions.c | 7 +++-- kernel/trace/trace_irqsoff.c | 2 +- kernel/trace/trace_sched_wakeup.c | 3 +- kernel/trace/trace_selftest.c | 15 +++++++++---- kernel/trace/trace_stack.c | 3 +- 10 files changed, 95 insertions(+), 42 deletions(-)arch/x86/include/asm/ftrace.h +21
-17@@ -4,26 +4,29 @@#ifdef __ASSEMBLY__ .macro MCOUNT_SAVE_FRAME - /* taken from glibc */ - subq $0x38, %rsp - movq %rax, (%rsp) - movq %rcx, 8(%rsp) - movq %rdx, 16(%rsp) - movq %rsi, 24(%rsp) - movq %rdi, 32(%rsp) - movq %r8, 40(%rsp) - movq %r9, 48(%rsp) +/* +* We add enough stack to save all regs, +* and we what we need in the location of pt_regs. + */ + subq $ORIG_RAX, %rsp + movq %rax, RAX(%rsp) + movq %rcx, RCX(%rsp) + movq %rdx, RDX(%rsp) + movq %rsi, RSI(%rsp) + movq %rdi, RDI(%rsp) + movq %r8, R8(%rsp) + movq %r9, R9(%rsp) .endm .macro MCOUNT_RESTORE_FRAME - movq 48(%rsp), %r9 - movq 40(%rsp), %r8 - movq 32(%rsp), %rdi - movq 24(%rsp), %rsi - movq 16(%rsp), %rdx - movq 8(%rsp), %rcx - movq (%rsp), %rax - addq $0x38, %rsp + movq R9(%rsp), %r9 + movq R8(%rsp), %r8 + movq RDI(%rsp), %rdi + movq RSI(%rsp), %rsi + movq RDX(%rsp), %rdx + movq RCX(%rsp), %rcx + movq RAX(%rsp), %rax + addq $ORIG_RAX, %rsp .endm #endif@@ -34,6 +37,7 @@#if defined(CONFIG_DYNAMIC_FTRACE ) && defined(CONFIG_X86_64 )#define ARCH_SUPPORTS_FTRACE_OPS 1 +#define ARCH_SUPPORTS_FTRACE_SAVE_REGS 1#endif #ifndef __ASSEMBLY__arch/x86/kernel/entry_64.S +0
-0@@ -78,7 +78,16 @@ ENTRY(ftrace_caller)I can see below code before save frame.
cmpl $0,
function_trace_stop
jneftrace_stubPlease pushf before comparing it. :)
Sometimes, the value of eflags is worth to watch.
I know that SF/ZF will be never used between
function call, so it is OK if the eflags is saved
inMCOUNT_SAVE_FRAME.Quoted 21 lines
arch/x86/kernel/entry_64.S +10
-1MCOUNT_SAVE_FRAME leaq function_trace_op, %rdx - movq 0x38(%rsp), %rdi + + cmpl $0, ftrace_save_regs + jne save_all_regs + +call_func: + + /* regs go into 4th parameter */ + leaq (%rsp), %rcx + + movq ORIG_RAX(%rsp), %rdi movq 8(%rbp), %rsi subq $MCOUNT_INSN_SIZE, %rdi@@ -96,6 +105,18 @@ GLOBAL(ftrace_stub) retq END(ftrace_caller)arch/x86/kernel/entry_64.S GLOBAL(ftrace_stub) · line 117
Quoted 10 lines
arch/x86/kernel/entry_64.S +10
-0+save_all_regs: + /* Save the rest of pt_regs */ + movq %r15, R15(%rsp) + movq %r14, R14(%rsp) + movq %r13, R13(%rsp) + movq %r12, R12(%rsp) + movq %r10, R10(%rsp) + movq %rbp, RBP(%rsp) + movq %rbx, RBX(%rsp) + jmp call_funcAt least, pt_regs.sp must be saved for accessing
vars on stack.arch/x86/kernel/entry_64.S GLOBAL(ftrace_stub) · line 122
Quoted 5 lines
arch/x86/kernel/entry_64.S +2
-0+ + #else /* ! CONFIG_DYNAMIC_FTRACE */ ENTRY(mcount) cmpl $0, function_trace_stopYou also need to restore the rest of
pt_regsifftrace_save_regsis true.Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerRe: [PATCH 3/5][RFC] ftrace: Return pt_regs to function trace callback (x86_64 only so
Quoted 4 lines · Masami Hiramatsu
Please note, kprobes is the function which basically provides a breakpoint handler in the kernel. Users expect that. So all registers should be provided as breakpoint interrupt does. That's what I said "transparently".
Well, I think I'm on the right track then. Because I'm working to get the function graph tracer to use this functionality as well.
I believe that I can make this work "transparently" too.
I'm now working on having ftrace use the breakpoint/update method as well as the stop_machine() method. If an arch has an alternative to stop_machine, then it can use that method instead.
-- Steve
Steven Rostedt
maintainerRFC PATCH 4/5 kprobes: Inverse taking of module_mutex with kprobe_mutex
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
Currently module_mutex is taken before kprobe_mutex, but this can cause issues when we have kprobes register ftrace, as the ftrace mutex is taken before enabling a tracepoint, which currently takes the module mutex.
If module_mutex is taken before kprobe_mutex, then we can not have kprobes use the ftrace infrastructure.
There seems to be no reason that the kprobe_mutex can't be taken before the module_mutex. Running lockdep shows that it is safe among the kernels I've run.
--- kernel/kprobes.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
kernel/kprobes.c +2 -2
@@ -561,9 +561,9 @@ static __kprobes void kprobe_optimizer(struct work_struct *work) {LIST_HEAD (free_list); +mutex_lock (&kprobe_mutex);/* Lock modules while optimizing kprobes */ mutex_lock (&module_mutex); -mutex_lock (&kprobe_mutex);/* * Step 1: Unoptimize kprobes and collect cleaned (unused and disarmed)
@@ -586,8 +586,8 @@ static __kprobes void kprobe_optimizer(struct work_struct *work)/* Step 4: Free cleaned kprobes after quiesence period */ do_free_cleaned_kprobes (&free_list); -mutex_unlock (&kprobe_mutex);mutex_unlock (&module_mutex); +mutex_unlock (&kprobe_mutex);/* Step 5: Kick optimizer again if needed */ if (!list_empty (&optimizing_list) || !list_empty (&unoptimizing_list))
Signature · 1 line
1.7.5.4
Steven Rostedt
maintainerRFC PATCH 5/5 kprobes: Use ftrace hooks when probing ftrace nops
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
Currently, if a probe is set at an ftrace nop, the probe will fail.
When -mfentry is used by ftrace (in the near future), the nop will be at the beginning of the function. This will prevent kprobes from hooking to the most common place that kprobes are attached.
Now that ftrace supports individual users as well as pt_regs passing, kprobes can use the ftrace infrastructure when a probe is placed on a ftrace nop.
--- include/linux/kprobes.h | 6 ++ kernel/kprobes.c | 163 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 160 insertions(+), 9 deletions(-)
include/linux/kprobes.h +6 -0
@@ -37,6 +37,7 @@#include <linux/spinlock.h> #include <linux/rcupdate.h> #include <linux/mutex.h> +#include <linux/ftrace.h> #ifdef CONFIG_KPROBES #include <asm/kprobes.h>
@@ -112,6 +113,11 @@ struct kprobe {/* copy of the original instruction */ struct arch_specific_insn ainsn; +#ifdef CONFIG_FUNCTION_TRACER +/* If it is possible to use ftrace to probe */ +struct ftrace_ops fops; +#endif +/* * Indicates various status flags. * Protected by kprobe_mutex after this kprobe is registered.
kernel/kprobes.c +154 -9
271 lines not on this page · raw message
Signature · 1 line
1.7.5.4
Re: [PATCH 5/5][RFC] kprobes: Use ftrace hooks when probing ftrace nops
Hi Steven,
As I suggested in another reply, I'm now attracted by the idea of using ftrace in kprobe-tracer, because of simplicity. Anyway, here is my review.
Quoted 11 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Currently, if a probe is set at an ftrace nop, the probe will fail.
When -mfentry is used by ftrace (in the near future), the nop will be at the beginning of the function. This will prevent kprobes from hooking to the most common place that kprobes are attached.
Now that ftrace supports individual users as well as
pt_regspassing, kprobes can use the ftrace infrastructure when a probe is placed on a ftrace nop.
My one general concern is the timing of enabling ftrace-based probe. Breakpoint-based kprobe (including optimized kprobe) is enabled right after registering. Users might expect that.
And AFAIK, dynamic ftraces handler will be enabled (activated) after a while, because it has to wait for an NMI, doesn't it?
And theoretically, this ftrace-based probe can't support jprobe, because it changes IP address. Nowadays, this may becomes minor problem (because someone who wants to trace function args can use kprobe-tracer), but still exist.
kernel/kprobes.c static void __kprobes __disarm_kprobe(struct kprobe *p,
Quoted 98 lines
Signed-off-by Steven Rostedt <[email protected]>--- include/linux/kprobes.h | 6 ++ kernel/kprobes.c | 163 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 160 insertions(+), 9 deletions(-)include/linux/kprobes.h +6
-0@@ -37,6 +37,7 @@#include <linux/spinlock.h> #include <linux/rcupdate.h> #include <linux/mutex.h> +#include <linux/ftrace.h> #ifdef CONFIG_KPROBES #include <asm/kprobes.h> @@ -112,6 +113,11 @@ struct kprobe {/* copy of the original instruction */ struct arch_specific_insn ainsn; +#ifdef CONFIG_FUNCTION_TRACER +/* If it is possible to use ftrace to probe */ +struct ftrace_ops fops; +#endif +/* * Indicates various status flags. * Protected by kprobe_mutex after this kprobe is registered. kernel/kprobes.c +35
-0@@ -102,6 +102,31 @@ static struct kprobe_blackpoint kprobe_blacklist[] = { {NULL} /* Terminator */ }; +#ifdef CONFIG_FUNCTION_TRACER +/* kprobe stub function for use when probe is not connected to ftrace */ +static void +kprobe_ftrace_stub (unsigned long ip,unsigned long pip, +struct ftrace_ops *op,struct pt_regs *pt_regs) +{ +} + +static bool ftrace_kprobe (struct kprobe *p) +{ +return p->fops.func && p->fops.func != kprobe_ftrace_stub; +} + +static void init_non_ftrace_kprobe (struct kprobe *p) +{ + p->fops.func = kprobe_ftrace_stub; +} + +#else +static bool ftrace_kprobe (struct kprobe *p) +{ +return false; +} +#endif +#ifdef __ARCH_WANT_KPROBES_INSN_SLOT/* * kprobe->ainsn.insn points to the copy of the instruction to be @@ -396,6 +421,9 @@ static __kprobes void free_aggr_kprobe(struct kprobe *p) {struct optimized_kprobe *op; +if (ftrace_kprobe (p)) +return ; + op = container_of(p, struct optimized_kprobe, kp);arch_remove_optimized_kprobe (op);arch_remove_kprobe (p);@@ -759,6 +787,9 @@ static __kprobes void try_to_optimize_kprobe(struct kprobe *p)struct kprobe *ap;struct optimized_kprobe *op; +if (ftrace_kprobe (p)) +return ; + ap =alloc_aggr_kprobe (p);if (!ap)return ;@@ -849,6 +880,10 @@ static void __kprobes __arm_kprobe(struct kprobe *p) {struct kprobe *_p; +/* Only arm non-ftrace probes */ +if (ftrace_kprobe (p)) +return ; +/* Check collision with other optimized kprobes */ _p =get_optimized_kprobe ((unsigned long )p->addr);if (unlikely (_p))@@ -864,6 +899,10 @@ static void __kprobes __disarm_kprobe(struct kprobe *p,
bool reopt)
kernel/kprobes.c static void __kprobes __disarm_kprobe(struct kprobe *p,
Quoted 11 lines
kernel/kprobes.c +4
-0{struct kprobe *_p; +/* Only disarm non-ftrace probes */ +if (ftrace_kprobe (p)) +return ; +unoptimize_kprobe (p, false);/* Try to unoptimize */ if (!kprobe_queued (p)) {@@ -878,13 +917,26 @@ static void __kprobes __disarm_kprobe(struct kprobe *p,
bool reopt)
Quoted 7 lines
kernel/kprobes.c +4
-0#else /* !CONFIG_OPTPROBES */ +static void __kprobes __arm_kprobe (struct kprobe *p) +{ +/* Only arm non-ftrace probes */ +if (!ftrace_kprobe (p))
kernel/kprobes.c static void __kprobes __disarm_kprobe(struct kprobe *p, bool reopt) · line 933
Quoted 10 lines
kernel/kprobes.c +10
-0+arch_arm_kprobe (p); +} + +/* Remove the breakpoint of a probe. Must be called with text_mutex locked */ +static void __kprobes __disarm_kprobe (struct kprobe *p,bool reopt) +{ +/* Only disarm non-ftrace probes */ +if (!ftrace_kprobe (p)) +arch_disarm_kprobe (p); +}
If it ignores disabling/enabling, kprobe_ftrace_callback must check kprobe_disabled(p) and skip it.
kernel/kprobes.c static __kprobes struct kprobe *alloc_aggr_kprobe(struct
Quoted 23 lines
kernel/kprobes.c +4
-3+#define optimize_kprobe (p) do {} while (0)#define unoptimize_kprobe (p, f) do {} while (0)#define kill_optimized_kprobe (p) do {} while (0)#define prepare_optimized_kprobe (p) do {} while (0)#define try_to_optimize_kprobe (p) do {} while (0) -#define __arm_kprobe (p) arch_arm_kprobe(p) -#define __disarm_kprobe (p, o) arch_disarm_kprobe(p)#define kprobe_disarmed (p) kprobe_disabled(p)#define wait_for_kprobe_optimizer () do {} while (0)@@ -897,7 +949,9 @@ static void reuse_unused_kprobe(struct kprobe *ap)static __kprobes void free_aggr_kprobe (struct kprobe *p) { -arch_remove_kprobe (p); + +if (!ftrace_kprobe (p)) +arch_remove_kprobe (p);kfree (p); }@@ -910,6 +964,12 @@ static __kprobes struct kprobe *alloc_aggr_kprobe(struct
kprobe *p)
Quoted 26 lines
kernel/kprobes.c +12
-0/* Arm a kprobe with text_mutex */ static void __kprobes arm_kprobe (struct kprobe *kp) { +/* ftrace probes can skip arch calls */ +if (ftrace_kprobe (kp)) { +register_ftrace_function (&kp->fops); +return ; + } +/* * Here, since __arm_kprobe() doesn't use stop_machine(), * this doesn't cause deadlock on text_mutex. So, we don't @@ -924,6 +984,12 @@ static void __kprobes arm_kprobe(struct kprobe *kp)static void __kprobes disarm_kprobe (struct kprobe *kp) {/* Ditto */ + +if (ftrace_kprobe (kp)) { +unregister_ftrace_function (&kp->fops); +return ; + } +mutex_lock (&text_mutex);__disarm_kprobe (kp, true);mutex_unlock (&text_mutex);
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1388
Quoted 10 lines
kernel/kprobes.c +7
-0@@ -1313,6 +1379,56 @@ static inline int check_kprobe_rereg(struct kprobe *p)return ret; } +#ifdef CONFIG_FUNCTION_TRACER +static notrace void +kprobe_ftrace_callback (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) +{ + struct kprobe *p = container_of(op, struct kprobe, fops); +
Here, we need to set up kprobe_ctlblk and some of pt_regs members, ip, cs and orig_ax as optimized_callback()@arch/x86/kernel/kprobes.c does.
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1391
Quoted 3 lines
kernel/kprobes.c +3
-0+/* A nop has been trapped, just run both handlers back to back */ +if (p->pre_handler) + p->pre_handler (p, pt_regs);
And increment regs->ip here for NOP.
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1394
Quoted 3 lines
kernel/kprobes.c +3
-0+if (p->post_handler) + p->post_handler (p, pt_regs,0 ); +}
Anyway, above operations strongly depends on arch, so kprobe_ftrace_callback should be moved to arch/*/kprobes.c.
And I think most of the code can be shared with optimized code.
Quoted 5 lines
kernel/kprobes.c +5
-0+ +static int use_ftrace_hook (struct kprobe *p) +{ +char str[KSYM_SYMBOL_LEN ]; +
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1409
Quoted 10 lines
kernel/kprobes.c +10
-0+/* see if this is an ftrace function */ +if (!ftrace_text_reserved (p->addr, p->addr)) { +/* make sure fops->func is nop */ +init_non_ftrace_kprobe (p); +return 0 ; + } + +/* If arch does not support pt_regs passing, bail */ +if (!ARCH_SUPPORTS_FTRACE_SAVE_REGS ) +return -EINVAL ;
Hmm, I think this should be checked at build time...
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1421
Quoted 12 lines
kernel/kprobes.c +12
-0+ +/* Use ftrace hook instead */ + +memset (&p->fops,0 ,sizeof (p->fops)); + +/* Find the function this is connected with this addr */ +kallsyms_lookup ((unsigned long )p->addr,NULL ,NULL ,NULL , str); + + p->fops.flags =FTRACE_OPS_FL_SAVE_REGS ; + p->fops.func = kprobe_ftrace_callback; + +ftrace_set_filter (&p->fops, str,strlen (str),1 );
Hmm, IMHO, ftrace_set_filter should not be called here, because there can be other kprobes are already registered on the same address. In that case, it is natural that we use an aggr_kprobe for handling several kprobes on same address. Or, kprobe hash table will have several different probes on same address.
Quoted 54 lines
kernel/kprobes.c +20
-5+ + return 0; +} +#else +static int use_ftrace_hook (struct kprobe *p) +{ +return 0 ; +} +#endif +int __kprobes register_kprobe (struct kprobe *p) {int ret =0 ;@@ -1329,11 +1445,14 @@ int __kprobes register_kprobe(struct kprobe *p)if (ret)return ret; + ret =use_ftrace_hook (p); +if (ret) +return ret; +jump_label_lock ();preempt_disable ();if (!kernel_text_address ((unsigned long ) p->addr) ||in_kprobes_functions ((unsigned long ) p->addr) || -ftrace_text_reserved (p->addr, p->addr) ||jump_label_text_reserved (p->addr, p->addr)) goto fail_with_jump_label;@@ -1384,15 +1503,17 @@ int __kprobes register_kprobe(struct kprobe *p) goto out; } - ret =arch_prepare_kprobe (p); -if (ret) - goto out; +if (!ftrace_kprobe (p)) { + ret =arch_prepare_kprobe (p); +if (ret) + goto out; + }INIT_HLIST_NODE (&p->hlist);hlist_add_head_rcu (&p->hlist, &kprobe_table[hash_ptr (p->addr,KPROBE_HASH_BITS )]); -if (!kprobes_all_disarmed && !kprobe_disabled (p)) +if (!ftrace_kprobe (p) && !kprobes_all_disarmed && !kprobe_disabled (p))__arm_kprobe (p);/* Try to optimize kprobe */ @@ -1400,6 +1521,12 @@ int __kprobes register_kprobe(struct kprobe *p) out:
kernel/kprobes.c int __kprobes register_kprobe(struct kprobe *p) · line 1532
Quoted 10 lines
kernel/kprobes.c +6
-0mutex_unlock (&text_mutex); + +/* ftrace kprobes must be set outside of text_mutex */ +if (!ret &&ftrace_kprobe (p) && + !kprobes_all_disarmed && !kprobe_disabled (p)) +arm_kprobe (p); +put_online_cpus ();jump_label_unlock ();mutex_unlock (&kprobe_mutex);
After this, we must handle some fails which can happen when probing on a module.
Quoted 28 lines
kernel/kprobes.c +12
-1@@ -2134,6 +2261,14 @@ static void __kprobes arm_all_kprobes(void) }mutex_unlock (&text_mutex); +/* ftrace kprobes are enabled outside of text_mutex */ +for (i =0 ; i <KPROBE_TABLE_SIZE ; i++) { + head = &kprobe_table[i]; +hlist_for_each_entry_rcu (p, node, head, hlist) +if (ftrace_kprobe (p) && !kprobe_disabled (p)) +arm_kprobe (p); + } + kprobes_all_disarmed = false;printk (KERN_INFO "Kprobes globally enabled\n" );@@ -2164,11 +2299,21 @@ static void __kprobes disarm_all_kprobes(void)for (i =0 ; i <KPROBE_TABLE_SIZE ; i++) { head = &kprobe_table[i];hlist_for_each_entry_rcu (p, node, head, hlist) { -if (!arch_trampoline_kprobe (p) && !kprobe_disabled (p)) +if (!ftrace_kprobe (p) && + !arch_trampoline_kprobe (p) && !kprobe_disabled (p))__disarm_kprobe (p, false); } }mutex_unlock (&text_mutex); + +/* ftrace kprobes are disabled outside of text_mutex */
kernel/kprobes.c static void __kprobes disarm_all_kprobes(void) · line 2319
Quoted 10 lines
kernel/kprobes.c +7
-0+for (i =0 ; i <KPROBE_TABLE_SIZE ; i++) { + head = &kprobe_table[i]; +hlist_for_each_entry_rcu (p, node, head, hlist) { +if (ftrace_kprobe (p) && !kprobe_disabled (p)) +disarm_kprobe (p); + } + }mutex_unlock (&kprobe_mutex);/* Wait for disarming all kprobes by optimizer */
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerRe: [PATCH 5/5][RFC] kprobes: Use ftrace hooks when probing ftrace nops
Quoted 5 lines · Masami Hiramatsu
Hi Steven,
As I suggested in another reply, I'm now attracted by the idea of using ftrace in kprobe-tracer, because of simplicity. Anyway, here is my review.
It may be a little simpler, but it defeats the purpose of what I'm trying to accomplish. I do want the ability to expand this to do other things than just trace_kprobe.
Quoted 14 lines
Quoted 11 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Currently, if a probe is set at an ftrace nop, the probe will fail.
When -mfentry is used by ftrace (in the near future), the nop will be at the beginning of the function. This will prevent kprobes from hooking to the most common place that kprobes are attached.
Now that ftrace supports individual users as well as
pt_regspassing, kprobes can use the ftrace infrastructure when a probe is placed on a ftrace nop.
Quoted 5 lines
My one general concern is the timing of enabling ftrace-based probe. Breakpoint-based kprobe (including optimized kprobe) is enabled right after registering. Users might expect that.
And AFAIK, dynamic ftraces handler will be enabled (activated) after a while, because it has to wait for an NMI, doesn't it?
There's no NMI needed. Not sure where you got that idea. When register_ftrace_function() is called, it will start tracing immediately. Note, stop_machine() is called, but we could fix that in the future too.
Quoted 5 lines
And theoretically, this ftrace-based probe can't support jprobe, because it changes IP address. Nowadays, this may becomes minor problem (because someone who wants to trace function args can use kprobe-tracer), but still exist.
I want to fix that too. :)
We don't need to worry about that until -mfentry exists. But once that does, then, yes, I want the ftrace version working for jprobe too.
Quoted 125 lines
kernel/kprobes.c static void __kprobes __disarm_kprobe(struct kprobe *p,
Quoted 100 lines
Signed-off-by Steven Rostedt <[email protected]>--- include/linux/kprobes.h | 6 ++ kernel/kprobes.c | 163 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 160 insertions(+), 9 deletions(-)include/linux/kprobes.h +6
-0@@ -37,6 +37,7 @@#include <linux/spinlock.h> #include <linux/rcupdate.h> #include <linux/mutex.h> +#include <linux/ftrace.h> #ifdef CONFIG_KPROBES #include <asm/kprobes.h> @@ -112,6 +113,11 @@ struct kprobe {/* copy of the original instruction */ struct arch_specific_insn ainsn; +#ifdef CONFIG_FUNCTION_TRACER +/* If it is possible to use ftrace to probe */ +struct ftrace_ops fops; +#endif +/* * Indicates various status flags. * Protected by kprobe_mutex after this kprobe is registered. kernel/kprobes.c +35
-0@@ -102,6 +102,31 @@ static struct kprobe_blackpoint kprobe_blacklist[] = { {NULL} /* Terminator */ }; +#ifdef CONFIG_FUNCTION_TRACER +/* kprobe stub function for use when probe is not connected to ftrace */ +static void +kprobe_ftrace_stub (unsigned long ip,unsigned long pip, +struct ftrace_ops *op,struct pt_regs *pt_regs) +{ +} + +static bool ftrace_kprobe (struct kprobe *p) +{ +return p->fops.func && p->fops.func != kprobe_ftrace_stub; +} + +static void init_non_ftrace_kprobe (struct kprobe *p) +{ + p->fops.func = kprobe_ftrace_stub; +} + +#else +static bool ftrace_kprobe (struct kprobe *p) +{ +return false; +} +#endif +#ifdef __ARCH_WANT_KPROBES_INSN_SLOT/* * kprobe->ainsn.insn points to the copy of the instruction to be @@ -396,6 +421,9 @@ static __kprobes void free_aggr_kprobe(struct kprobe *p) {struct optimized_kprobe *op; +if (ftrace_kprobe (p)) +return ; + op = container_of(p, struct optimized_kprobe, kp);arch_remove_optimized_kprobe (op);arch_remove_kprobe (p);@@ -759,6 +787,9 @@ static __kprobes void try_to_optimize_kprobe(struct kprobe *p)struct kprobe *ap;struct optimized_kprobe *op; +if (ftrace_kprobe (p)) +return ; + ap =alloc_aggr_kprobe (p);if (!ap)return ;@@ -849,6 +880,10 @@ static void __kprobes __arm_kprobe(struct kprobe *p) {struct kprobe *_p; +/* Only arm non-ftrace probes */ +if (ftrace_kprobe (p)) +return ; +/* Check collision with other optimized kprobes */ _p =get_optimized_kprobe ((unsigned long )p->addr);if (unlikely (_p))@@ -864,6 +899,10 @@ static void __kprobes __disarm_kprobe(struct kprobe *p,bool reopt)
kernel/kprobes.c static void __kprobes __disarm_kprobe(struct kprobe *p,
Quoted 11 lines
kernel/kprobes.c +4
-0{struct kprobe *_p; +/* Only disarm non-ftrace probes */ +if (ftrace_kprobe (p)) +return ; +unoptimize_kprobe (p, false);/* Try to unoptimize */ if (!kprobe_queued (p)) {@@ -878,13 +917,26 @@ static void __kprobes __disarm_kprobe(struct kprobe *p,bool reopt)
Quoted 12 lines
kernel/kprobes.c +9
-0#else /* !CONFIG_OPTPROBES */ +static void __kprobes __arm_kprobe (struct kprobe *p) +{ +/* Only arm non-ftrace probes */ +if (!ftrace_kprobe (p)) +arch_arm_kprobe (p); +} + +/* Remove the breakpoint of a probe. Must be called with text_mutex locked */ +static void __kprobes __disarm_kprobe (struct kprobe *p,bool reopt)
Quoted 8 lines
kernel/kprobes.c static void __kprobes __disarm_kprobe(struct kprobe *p, bool reopt) · line 933
Quoted 5 lines
kernel/kprobes.c +5
-0+{ +/* Only disarm non-ftrace probes */ +if (!ftrace_kprobe (p)) +arch_disarm_kprobe (p); +}If it ignores disabling/enabling,
kprobe_ftrace_callbackmust checkkprobe_disabled(p)and skip it.
No, the callers of __(dis)arm_kprobe() also call the (dis)arm_kprobe() later, which calls (un)register_ftrace_function(). The reason we can't call the ftrace register functions here is because they call stop_machine() and then we get into a deadlock with the text_mutex. The places that call __(dis)arm_kprobe() later call (dis)arm_kprobe() after releasing the text_mutex.
Quoted 54 lines
kernel/kprobes.c static __kprobes struct kprobe *alloc_aggr_kprobe(struct
Quoted 24 lines
kernel/kprobes.c +4
-3+#define optimize_kprobe (p) do {} while (0)#define unoptimize_kprobe (p, f) do {} while (0)#define kill_optimized_kprobe (p) do {} while (0)#define prepare_optimized_kprobe (p) do {} while (0)#define try_to_optimize_kprobe (p) do {} while (0) -#define __arm_kprobe (p) arch_arm_kprobe(p) -#define __disarm_kprobe (p, o) arch_disarm_kprobe(p)#define kprobe_disarmed (p) kprobe_disabled(p)#define wait_for_kprobe_optimizer () do {} while (0)@@ -897,7 +949,9 @@ static void reuse_unused_kprobe(struct kprobe *ap)static __kprobes void free_aggr_kprobe (struct kprobe *p) { -arch_remove_kprobe (p); + +if (!ftrace_kprobe (p)) +arch_remove_kprobe (p);kfree (p); }@@ -910,6 +964,12 @@ static __kprobes struct kprobe *alloc_aggr_kprobe(structkprobe *p)
Quoted 29 lines
kernel/kprobes.c +12
-0/* Arm a kprobe with text_mutex */ static void __kprobes arm_kprobe (struct kprobe *kp) { +/* ftrace probes can skip arch calls */ +if (ftrace_kprobe (kp)) { +register_ftrace_function (&kp->fops); +return ; + } +/* * Here, since __arm_kprobe() doesn't use stop_machine(), * this doesn't cause deadlock on text_mutex. So, we don't @@ -924,6 +984,12 @@ static void __kprobes arm_kprobe(struct kprobe *kp)static void __kprobes disarm_kprobe (struct kprobe *kp) {/* Ditto */ + +if (ftrace_kprobe (kp)) { +unregister_ftrace_function (&kp->fops); +return ; + } +mutex_lock (&text_mutex);__disarm_kprobe (kp, true);mutex_unlock (&text_mutex);@@ -1313,6 +1379,56 @@ static inline int check_kprobe_rereg(struct kprobe *p)return ret; }
Quoted 11 lines
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1388
Quoted 7 lines
kernel/kprobes.c +7
-0+#ifdef CONFIG_FUNCTION_TRACER +static notrace void +kprobe_ftrace_callback (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) +{ + struct kprobe *p = container_of(op, struct kprobe, fops); +Here, we need to set up
kprobe_ctlblkand some ofpt_regsmembers, ip, cs andorig_axas optimized_callback()@arch/x86/kernel/kprobes.c does.
I'm curious to what this is used for? It doesn't seem to be needed for the generic kprobes. Because we know the probe was on a nop, there's no need to simulate the operation. IOW, there's no need for singlestep() or other gdb like operations.
Quoted 6 lines
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1391
Quoted 4 lines
kernel/kprobes.c +3
-0+/* A nop has been trapped, just run both handlers back to back */ +if (p->pre_handler) + p->pre_handler (p, pt_regs);And increment
regs->iphere for NOP.
Does the post_handler() expect the ip to be after the call? Thus a post_handle() is the same as pre_handle() on rip+next_ins?
Quoted 9 lines
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1394
Quoted 4 lines
kernel/kprobes.c +3
-0+if (p->post_handler) + p->post_handler (p, pt_regs,0 ); +}Anyway, above operations strongly depends on arch, so
kprobe_ftrace_callbackshould be moved toarch/*/kprobes.c.And I think most of the code can be shared with optimized code.
Not sure why. Except if regs->ip needs to be incremented. And that can be a per arch header file. Remember, the ftrace version has no need for single stepping like the optimized version does. ftrace replaces a nop, where as other kprobes replace actual instructions. This is what make the ftrace version so much less complex.
Quoted 10 lines
Quoted 10 lines
kernel/kprobes.c +9
-0+ +static int use_ftrace_hook (struct kprobe *p) +{ +char str[KSYM_SYMBOL_LEN ]; + +/* see if this is an ftrace function */ +if (!ftrace_text_reserved (p->addr, p->addr)) { +/* make sure fops->func is nop */ +init_non_ftrace_kprobe (p);
Quoted 8 lines
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1409
Quoted 6 lines
kernel/kprobes.c +6
-0+return 0 ; + } + +/* If arch does not support pt_regs passing, bail */ +if (!ARCH_SUPPORTS_FTRACE_SAVE_REGS ) +return -EINVAL ;Hmm, I think this should be checked at build time...
This is actually keeping the same logic that exists now. See below, we removed the check of ftrace_text_reserved() from the conditions that make register_kprobe() return -EINVAL. Now if the arch supports FTRACE_SAVE_REGS, it can handle the ftrace_text_reserved(), if not, then it goes back to its original behavior.
The only way to remove the later code is with #ifdef ugliness, and I didn't want to add that.
Quoted 11 lines
Quoted 11 lines
kernel/kprobes.c +10
-0+ +/* Use ftrace hook instead */ + +memset (&p->fops,0 ,sizeof (p->fops)); + +/* Find the function this is connected with this addr */ +kallsyms_lookup ((unsigned long )p->addr,NULL ,NULL ,NULL , str); + + p->fops.flags =FTRACE_OPS_FL_SAVE_REGS ; + p->fops.func = kprobe_ftrace_callback;
Quoted 8 lines
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1421
Quoted 2 lines
kernel/kprobes.c +2
-0+ +ftrace_set_filter (&p->fops, str,strlen (str),1 );Hmm, IMHO,
ftrace_set_filtershould not be called here, because there can be other kprobes are already registered on the same address. In that case, it is natural that we use anaggr_kprobefor handling several kprobes on same address. Or, kprobe hash table will have several different probes on same address.
The ftrace_set_filter() only updates the p->fops to what it will trace. It's the register_ftrace_function() that enables the ftrace tracing, and that is done with the arm_kprobe() call. If that's where the aggr_kprobe enables its call, then that will be the only probe that is called.
Now I need to re-examine how the aggr_kprobes work. Does it have its own handler to call multiple probe->handlers?
Quoted 54 lines
Quoted 54 lines
kernel/kprobes.c +20
-5+ + return 0; +} +#else +static int use_ftrace_hook (struct kprobe *p) +{ +return 0 ; +} +#endif +int __kprobes register_kprobe (struct kprobe *p) {int ret =0 ;@@ -1329,11 +1445,14 @@ int __kprobes register_kprobe(struct kprobe *p)if (ret)return ret; + ret =use_ftrace_hook (p); +if (ret) +return ret; +jump_label_lock ();preempt_disable ();if (!kernel_text_address ((unsigned long ) p->addr) ||in_kprobes_functions ((unsigned long ) p->addr) || -ftrace_text_reserved (p->addr, p->addr) ||jump_label_text_reserved (p->addr, p->addr)) goto fail_with_jump_label;@@ -1384,15 +1503,17 @@ int __kprobes register_kprobe(struct kprobe *p) goto out; } - ret =arch_prepare_kprobe (p); -if (ret) - goto out; +if (!ftrace_kprobe (p)) { + ret =arch_prepare_kprobe (p); +if (ret) + goto out; + }INIT_HLIST_NODE (&p->hlist);hlist_add_head_rcu (&p->hlist, &kprobe_table[hash_ptr (p->addr,KPROBE_HASH_BITS )]); -if (!kprobes_all_disarmed && !kprobe_disabled (p)) +if (!ftrace_kprobe (p) && !kprobes_all_disarmed && !kprobe_disabled (p))__arm_kprobe (p);/* Try to optimize kprobe */ @@ -1400,6 +1521,12 @@ int __kprobes register_kprobe(struct kprobe *p)
Quoted 14 lines
kernel/kprobes.c int __kprobes register_kprobe(struct kprobe *p) · line 1532
Quoted 11 lines
kernel/kprobes.c +6
-0out:mutex_unlock (&text_mutex); + +/* ftrace kprobes must be set outside of text_mutex */ +if (!ret &&ftrace_kprobe (p) && + !kprobes_all_disarmed && !kprobe_disabled (p)) +arm_kprobe (p); +put_online_cpus ();jump_label_unlock ();mutex_unlock (&kprobe_mutex);After this, we must handle some fails which can happen when probing on a module.
What problems that were added by ftrace that isn't a problem with normal probes?
Quoted 39 lines
Quoted 39 lines
kernel/kprobes.c +19
-1@@ -2134,6 +2261,14 @@ static void __kprobes arm_all_kprobes(void) }mutex_unlock (&text_mutex); +/* ftrace kprobes are enabled outside of text_mutex */ +for (i =0 ; i <KPROBE_TABLE_SIZE ; i++) { + head = &kprobe_table[i]; +hlist_for_each_entry_rcu (p, node, head, hlist) +if (ftrace_kprobe (p) && !kprobe_disabled (p)) +arm_kprobe (p); + } + kprobes_all_disarmed = false;printk (KERN_INFO "Kprobes globally enabled\n" );@@ -2164,11 +2299,21 @@ static void __kprobes disarm_all_kprobes(void)for (i =0 ; i <KPROBE_TABLE_SIZE ; i++) { head = &kprobe_table[i];hlist_for_each_entry_rcu (p, node, head, hlist) { -if (!arch_trampoline_kprobe (p) && !kprobe_disabled (p)) +if (!ftrace_kprobe (p) && + !arch_trampoline_kprobe (p) && !kprobe_disabled (p))__disarm_kprobe (p, false); } }mutex_unlock (&text_mutex); + +/* ftrace kprobes are disabled outside of text_mutex */ +for (i =0 ; i <KPROBE_TABLE_SIZE ; i++) { + head = &kprobe_table[i]; +hlist_for_each_entry_rcu (p, node, head, hlist) { +if (ftrace_kprobe (p) && !kprobe_disabled (p)) +disarm_kprobe (p); + } + }mutex_unlock (&kprobe_mutex);
Quoted 4 lines
kernel/kprobes.c static void __kprobes disarm_all_kprobes(void) · line 2319
Quoted 1 line
kernel/kprobes.c +0
-0/* Wait for disarming all kprobes by optimizer */ Thank you,
Thanks for taking the time for your review!
-- Steve
Re: [PATCH 5/5][RFC] kprobes: Use ftrace hooks when probing ftrace nops
Quoted 10 lines · Steven Rostedt
Quoted 5 lines · Masami Hiramatsu
Hi Steven,
As I suggested in another reply, I'm now attracted by the idea of using ftrace in kprobe-tracer, because of simplicity. Anyway, here is my review.
It may be a little simpler, but it defeats the purpose of what I'm trying to accomplish. I do want the ability to expand this to do other things than just
trace_kprobe.
OK, could you tell me what would you like to accomplish with this? I thought this was a challange to trace function arguments with low-overhead. And if so, I think expanding trace_kprobe (a.k.a. dynamic-events) to handle ftrace with pt_regs is a better way.
What is the good point to expand kprobes itself instead of using ftrace directly?
If you consider -mfentry reduces the kprobes usefulness because it prevents probe function entry, I think we can put kprobes just after mcount code because mcount code does not change anything, and this doesn't affect anything.
E.g. if user puts kprobe on a function+0, it automatically moved to function+5, but kp->addr is still same as the function address. With this change, we don't need to change anything. User will see the IP address in pre_handler() is function+6 (5 for mcount and 1 for int3), and it will be acceptable because real probed IP address must be gotten from kp->addr.
Quoted 19 lines
Quoted 13 lines
Quoted 11 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Currently, if a probe is set at an ftrace nop, the probe will fail.
When -mfentry is used by ftrace (in the near future), the nop will be at the beginning of the function. This will prevent kprobes from hooking to the most common place that kprobes are attached.
Now that ftrace supports individual users as well as
pt_regspassing, kprobes can use the ftrace infrastructure when a probe is placed on a ftrace nop.Quoted 5 lines
My one general concern is the timing of enabling ftrace-based probe. Breakpoint-based kprobe (including optimized kprobe) is enabled right after registering. Users might expect that.
And AFAIK, dynamic ftraces handler will be enabled (activated) after a while, because it has to wait for an NMI, doesn't it?
Quoted 3 lines
There's no NMI needed. Not sure where you got that idea. When
register_ftrace_function()is called, it will start tracing immediately. Note,stop_machine()is called, but we could fix that in the future too.
Ah, I see. So timing issue will be minor (even though calling stop_machine() each time might be solved).
Quoted 9 lines
Quoted 4 lines
And theoretically, this ftrace-based probe can't support jprobe, because it changes IP address. Nowadays, this may becomes minor problem (because someone who wants to trace function args can use kprobe-tracer), but still exist.
I want to fix that too. :)
We don't need to worry about that until -mfentry exists. But once that does, then, yes, I want the ftrace version working for jprobe too.
OK, changing IP is not so hard.
Quoted 70 lines
Quoted 70 lines
Quoted 70 lines
Signed-off-by Steven Rostedt <[email protected]>--- include/linux/kprobes.h | 6 ++ kernel/kprobes.c | 163 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 160 insertions(+), 9 deletions(-)include/linux/kprobes.h +6
-0@@ -37,6 +37,7 @@#include <linux/spinlock.h> #include <linux/rcupdate.h> #include <linux/mutex.h> +#include <linux/ftrace.h> #ifdef CONFIG_KPROBES #include <asm/kprobes.h> @@ -112,6 +113,11 @@ struct kprobe {/* copy of the original instruction */ struct arch_specific_insn ainsn; +#ifdef CONFIG_FUNCTION_TRACER +/* If it is possible to use ftrace to probe */ +struct ftrace_ops fops; +#endif +/* * Indicates various status flags. * Protected by kprobe_mutex after this kprobe is registered. kernel/kprobes.c +25
-0@@ -102,6 +102,31 @@ static struct kprobe_blackpoint kprobe_blacklist[] = { {NULL} /* Terminator */ }; +#ifdef CONFIG_FUNCTION_TRACER +/* kprobe stub function for use when probe is not connected to ftrace */ +static void +kprobe_ftrace_stub (unsigned long ip,unsigned long pip, +struct ftrace_ops *op,struct pt_regs *pt_regs) +{ +} + +static bool ftrace_kprobe (struct kprobe *p) +{ +return p->fops.func && p->fops.func != kprobe_ftrace_stub; +} + +static void init_non_ftrace_kprobe (struct kprobe *p) +{ + p->fops.func = kprobe_ftrace_stub; +} + +#else +static bool ftrace_kprobe (struct kprobe *p) +{ +return false; +} +#endif +#ifdef __ARCH_WANT_KPROBES_INSN_SLOT/* * kprobe->ainsn.insn points to the copy of the instruction to be @@ -396,6 +421,9 @@ static __kprobes void free_aggr_kprobe(struct kprobe *p) {struct optimized_kprobe *op;
Quoted 7 lines
Quoted 7 lines
kernel/kprobes.c static __kprobes void try_to_optimize_kprobe(struct
Quoted 7 lines
kernel/kprobes.c +3
-0+if (ftrace_kprobe (p)) +return ; + op = container_of(p, struct optimized_kprobe, kp);arch_remove_optimized_kprobe (op);arch_remove_kprobe (p);@@ -759,6 +787,9 @@ static __kprobes void try_to_optimize_kprobe(struct
kprobe *p)
Quoted 55 lines
Quoted 46 lines
kernel/kprobes.c static void __kprobes __disarm_kprobe(struct kprobe *p,
Quoted 21 lines
kernel/kprobes.c +7
-0struct kprobe *ap;struct optimized_kprobe *op; +if (ftrace_kprobe (p)) +return ; + ap =alloc_aggr_kprobe (p);if (!ap)return ;@@ -849,6 +880,10 @@ static void __kprobes __arm_kprobe(struct kprobe *p) {struct kprobe *_p; +/* Only arm non-ftrace probes */ +if (ftrace_kprobe (p)) +return ; +/* Check collision with other optimized kprobes */ _p =get_optimized_kprobe ((unsigned long )p->addr);if (unlikely (_p))@@ -864,6 +899,10 @@ static void __kprobes __disarm_kprobe(struct kprobe *p,bool reopt)
kernel/kprobes.c static void __kprobes __disarm_kprobe(struct kprobe *p,
Quoted 11 lines
kernel/kprobes.c +4
-0{struct kprobe *_p; +/* Only disarm non-ftrace probes */ +if (ftrace_kprobe (p)) +return ; +unoptimize_kprobe (p, false);/* Try to unoptimize */ if (!kprobe_queued (p)) {@@ -878,13 +917,26 @@ static void __kprobes __disarm_kprobe(struct kprobe *p,bool reopt)
Quoted 12 lines
kernel/kprobes.c +9
-0#else /* !CONFIG_OPTPROBES */ +static void __kprobes __arm_kprobe (struct kprobe *p) +{ +/* Only arm non-ftrace probes */ +if (!ftrace_kprobe (p)) +arch_arm_kprobe (p); +} + +/* Remove the breakpoint of a probe. Must be called with text_mutex locked */ +static void __kprobes __disarm_kprobe (struct kprobe *p,bool reopt)Quoted 8 lines
kernel/kprobes.c static void __kprobes __disarm_kprobe(struct kprobe *p, bool reopt) · line 933
Quoted 5 lines
kernel/kprobes.c +5
-0+{ +/* Only disarm non-ftrace probes */ +if (!ftrace_kprobe (p)) +arch_disarm_kprobe (p); +}If it ignores disabling/enabling,
kprobe_ftrace_callbackmust checkkprobe_disabled(p)and skip it.
Quoted 6 lines
No, the callers of __(dis)arm_kprobe() also call the (dis)arm_kprobe() later, which calls (un)register_ftrace_function(). The reason we can't call the ftrace register functions here is because they call
stop_machine()and then we get into a deadlock with thetext_mutex. The places that call __(dis)arm_kprobe() later call (dis)arm_kprobe() after releasing thetext_mutex.
OK.
Quoted 65 lines
Quoted 53 lines
kernel/kprobes.c static __kprobes struct kprobe *alloc_aggr_kprobe(struct
Quoted 23 lines
kernel/kprobes.c +4
-3+#define optimize_kprobe (p) do {} while (0)#define unoptimize_kprobe (p, f) do {} while (0)#define kill_optimized_kprobe (p) do {} while (0)#define prepare_optimized_kprobe (p) do {} while (0)#define try_to_optimize_kprobe (p) do {} while (0) -#define __arm_kprobe (p) arch_arm_kprobe(p) -#define __disarm_kprobe (p, o) arch_disarm_kprobe(p)#define kprobe_disarmed (p) kprobe_disabled(p)#define wait_for_kprobe_optimizer () do {} while (0)@@ -897,7 +949,9 @@ static void reuse_unused_kprobe(struct kprobe *ap)static __kprobes void free_aggr_kprobe (struct kprobe *p) { -arch_remove_kprobe (p); + +if (!ftrace_kprobe (p)) +arch_remove_kprobe (p);kfree (p); }@@ -910,6 +964,12 @@ static __kprobes struct kprobe *alloc_aggr_kprobe(structkprobe *p)
Quoted 29 lines
kernel/kprobes.c +12
-0/* Arm a kprobe with text_mutex */ static void __kprobes arm_kprobe (struct kprobe *kp) { +/* ftrace probes can skip arch calls */ +if (ftrace_kprobe (kp)) { +register_ftrace_function (&kp->fops); +return ; + } +/* * Here, since __arm_kprobe() doesn't use stop_machine(), * this doesn't cause deadlock on text_mutex. So, we don't @@ -924,6 +984,12 @@ static void __kprobes arm_kprobe(struct kprobe *kp)static void __kprobes disarm_kprobe (struct kprobe *kp) {/* Ditto */ + +if (ftrace_kprobe (kp)) { +unregister_ftrace_function (&kp->fops); +return ; + } +mutex_lock (&text_mutex);__disarm_kprobe (kp, true);mutex_unlock (&text_mutex);@@ -1313,6 +1379,56 @@ static inline int check_kprobe_rereg(struct kprobe *p)return ret; }Quoted 11 lines
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1388
Quoted 7 lines
kernel/kprobes.c +7
-0+#ifdef CONFIG_FUNCTION_TRACER +static notrace void +kprobe_ftrace_callback (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) +{ + struct kprobe *p = container_of(op, struct kprobe, fops); +Here, we need to set up
kprobe_ctlblkand some ofpt_regsmembers, ip, cs andorig_axas optimized_callback()@arch/x86/kernel/kprobes.c does.
Quoted 4 lines
I'm curious to what this is used for? It doesn't seem to be needed for the generic kprobes. Because we know the probe was on a nop, there's no need to simulate the operation. IOW, there's no need for
singlestep()or other gdb like operations.
That is not for the singlestep but the handler may expect that, because kprobes handler doesn't know it is hit on a breakpoint, jump or mcount call.
So, we have to simulate it as much as possible. Or, it's not the kprobes.
Quoted 9 lines
Quoted 6 lines
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1391
Quoted 4 lines
kernel/kprobes.c +3
-0+/* A nop has been trapped, just run both handlers back to back */ +if (p->pre_handler) + p->pre_handler (p, pt_regs);And increment
regs->iphere for NOP.Does the
post_handler()expect the ip to be after the call? Thus apost_handle()is the same aspre_handle()on rip+next_ins?
Usually, post_handler() is for watching the behavior of probed instruction. If the kprobe puts a breakpoint on "addl $10, %eax", post_handler() will see the value of %eax is incremented by 10.
Quoted 7 lines
Quoted 7 lines
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1394
Quoted 3 lines
kernel/kprobes.c +3
-0+if (p->post_handler) + p->post_handler (p, pt_regs,0 ); +}Anyway, above operations strongly depends on arch, so
kprobe_ftrace_callbackshould be moved toarch/*/kprobes.c.
Quoted 7 lines
Quoted 1 line
And I think most of the code can be shared with optimized code.
Not sure why. Except if
regs->ipneeds to be incremented. And that can be a per arch header file. Remember, the ftrace version has no need for single stepping like the optimized version does. ftrace replaces a nop, where as other kprobes replace actual instructions. This is what make the ftrace version so much less complex.
Yeah, I just meant about preparing code. Hmm, putting that kind of register fixup in the arch header may be a good idea.
Quoted 18 lines
Quoted 9 lines
Quoted 9 lines
kernel/kprobes.c +9
-0+ +static int use_ftrace_hook (struct kprobe *p) +{ +char str[KSYM_SYMBOL_LEN ]; + +/* see if this is an ftrace function */ +if (!ftrace_text_reserved (p->addr, p->addr)) { +/* make sure fops->func is nop */ +init_non_ftrace_kprobe (p);Quoted 8 lines
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1409
Quoted 6 lines
kernel/kprobes.c +6
-0+return 0 ; + } + +/* If arch does not support pt_regs passing, bail */ +if (!ARCH_SUPPORTS_FTRACE_SAVE_REGS ) +return -EINVAL ;Hmm, I think this should be checked at build time...
Quoted 8 lines
This is actually keeping the same logic that exists now. See below, we removed the check of
ftrace_text_reserved()from the conditions that makeregister_kprobe()return-EINVAL. Now if the arch supportsFTRACE_SAVE_REGS, it can handle theftrace_text_reserved(), if not, then it goes back to its original behavior.The only way to remove the later code is with #ifdef ugliness, and I didn't want to add that.
OK, it's for avoiding ugliness.
Quoted 21 lines
Quoted 12 lines
Quoted 12 lines
kernel/kprobes.c +10
-0+ +/* Use ftrace hook instead */ + +memset (&p->fops,0 ,sizeof (p->fops)); + +/* Find the function this is connected with this addr */ +kallsyms_lookup ((unsigned long )p->addr,NULL ,NULL ,NULL , str); + + p->fops.flags =FTRACE_OPS_FL_SAVE_REGS ; + p->fops.func = kprobe_ftrace_callback;Quoted 8 lines
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1421
Quoted 2 lines
kernel/kprobes.c +2
-0+ +ftrace_set_filter (&p->fops, str,strlen (str),1 );Hmm, IMHO,
ftrace_set_filtershould not be called here, because there can be other kprobes are already registered on the same address. In that case, it is natural that we use anaggr_kprobefor handling several kprobes on same address. Or, kprobe hash table will have several different probes on same address.
Quoted 4 lines
The
ftrace_set_filter()only updates thep->fopsto what it will trace. It's theregister_ftrace_function()that enables the ftrace tracing, and that is done with thearm_kprobe()call. If that's where theaggr_kprobeenables its call, then that will be the only probe that is called.
Ah, OK, I see. so ftrace_set_filter() just prepares p->fops, not registers something in ftrace.
Quoted 2 lines
Now I need to re-examine how the
aggr_kprobeswork. Does it have its own handler to call multipleprobe->handlers?
Yes, aggr_pre/fault/post/break_handler() are those.
Quoted 68 lines
Quoted 53 lines
Quoted 53 lines
kernel/kprobes.c +20
-5+ + return 0; +} +#else +static int use_ftrace_hook (struct kprobe *p) +{ +return 0 ; +} +#endif +int __kprobes register_kprobe (struct kprobe *p) {int ret =0 ;@@ -1329,11 +1445,14 @@ int __kprobes register_kprobe(struct kprobe *p)if (ret)return ret; + ret =use_ftrace_hook (p); +if (ret) +return ret; +jump_label_lock ();preempt_disable ();if (!kernel_text_address ((unsigned long ) p->addr) ||in_kprobes_functions ((unsigned long ) p->addr) || -ftrace_text_reserved (p->addr, p->addr) ||jump_label_text_reserved (p->addr, p->addr)) goto fail_with_jump_label;@@ -1384,15 +1503,17 @@ int __kprobes register_kprobe(struct kprobe *p) goto out; } - ret =arch_prepare_kprobe (p); -if (ret) - goto out; +if (!ftrace_kprobe (p)) { + ret =arch_prepare_kprobe (p); +if (ret) + goto out; + }INIT_HLIST_NODE (&p->hlist);hlist_add_head_rcu (&p->hlist, &kprobe_table[hash_ptr (p->addr,KPROBE_HASH_BITS )]); -if (!kprobes_all_disarmed && !kprobe_disabled (p)) +if (!ftrace_kprobe (p) && !kprobes_all_disarmed && !kprobe_disabled (p))__arm_kprobe (p);/* Try to optimize kprobe */ @@ -1400,6 +1521,12 @@ int __kprobes register_kprobe(struct kprobe *p)Quoted 14 lines
kernel/kprobes.c int __kprobes register_kprobe(struct kprobe *p) · line 1532
Quoted 11 lines
kernel/kprobes.c +6
-0out:mutex_unlock (&text_mutex); + +/* ftrace kprobes must be set outside of text_mutex */ +if (!ret &&ftrace_kprobe (p) && + !kprobes_all_disarmed && !kprobe_disabled (p)) +arm_kprobe (p); +put_online_cpus ();jump_label_unlock ();mutex_unlock (&kprobe_mutex);After this, we must handle some fails which can happen when probing on a module.
Quoted 2 lines
What problems that were added by ftrace that isn't a problem with normal probes?
It was my misunderstand of ftrace_set_filter(). No need to do anything.
Quoted 50 lines
Quoted 40 lines
Quoted 40 lines
kernel/kprobes.c +19
-1@@ -2134,6 +2261,14 @@ static void __kprobes arm_all_kprobes(void) }mutex_unlock (&text_mutex); +/* ftrace kprobes are enabled outside of text_mutex */ +for (i =0 ; i <KPROBE_TABLE_SIZE ; i++) { + head = &kprobe_table[i]; +hlist_for_each_entry_rcu (p, node, head, hlist) +if (ftrace_kprobe (p) && !kprobe_disabled (p)) +arm_kprobe (p); + } + kprobes_all_disarmed = false;printk (KERN_INFO "Kprobes globally enabled\n" );@@ -2164,11 +2299,21 @@ static void __kprobes disarm_all_kprobes(void)for (i =0 ; i <KPROBE_TABLE_SIZE ; i++) { head = &kprobe_table[i];hlist_for_each_entry_rcu (p, node, head, hlist) { -if (!arch_trampoline_kprobe (p) && !kprobe_disabled (p)) +if (!ftrace_kprobe (p) && + !arch_trampoline_kprobe (p) && !kprobe_disabled (p))__disarm_kprobe (p, false); } }mutex_unlock (&text_mutex); + +/* ftrace kprobes are disabled outside of text_mutex */ +for (i =0 ; i <KPROBE_TABLE_SIZE ; i++) { + head = &kprobe_table[i]; +hlist_for_each_entry_rcu (p, node, head, hlist) { +if (ftrace_kprobe (p) && !kprobe_disabled (p)) +disarm_kprobe (p); + } + }mutex_unlock (&kprobe_mutex);Quoted 4 lines
kernel/kprobes.c static void __kprobes disarm_all_kprobes(void) · line 2319
Quoted 1 line
kernel/kprobes.c +0
-0/* Wait for disarming all kprobes by optimizer */ Thank you,
Thanks for taking the time for your review!
-- Steve
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Re: [PATCH 5/5][RFC] kprobes: Use ftrace hooks when probing ftrace nops
In reply to Steven RostedtQuoted 1 line · Steven Rostedt
On Thu, 2011-08-11 at 16:41 +0900, Masami Hiramatsu wrote:
...
Quoted 12 lines
Quoted 11 lines
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1388
Quoted 7 lines
kernel/kprobes.c +7
-0+#ifdef CONFIG_FUNCTION_TRACER +static notrace void +kprobe_ftrace_callback (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) +{ + struct kprobe *p = container_of(op, struct kprobe, fops); +Here, we need to set up
kprobe_ctlblkand some ofpt_regsmembers, ip, cs andorig_axas optimized_callback()@arch/x86/kernel/kprobes.c does.
Quoted 4 lines
I'm curious to what this is used for? It doesn't seem to be needed for the generic kprobes. Because we know the probe was on a nop, there's no need to simulate the operation. IOW, there's no need for
singlestep()or other gdb like operations.
It is needed to handle recursion, for instance. If in the rare case a kprobe handler calls another routine which also has a kprobe installed (and so on), we just bypass calling the 2nd kprobe's handlers. To do this and to set back the original kprobe context, we track the kprobe state in the per_cpu kprobe_ctlblk.
Ananth
Steven Rostedt
maintainerRe: [PATCH 5/5][RFC] kprobes: Use ftrace hooks when probing ftrace nops
Quoted 22 lines · Ananth N Mavinakayanahalli
Quoted 1 line · Steven Rostedt
On Thu, 2011-08-11 at 16:41 +0900, Masami Hiramatsu wrote:
...
Quoted 12 lines
Quoted 11 lines
kernel/kprobes.c static inline int check_kprobe_rereg(struct kprobe *p) · line 1388
Quoted 7 lines
kernel/kprobes.c +7
-0+#ifdef CONFIG_FUNCTION_TRACER +static notrace void +kprobe_ftrace_callback (unsigned long ip,unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *pt_regs) +{ + struct kprobe *p = container_of(op, struct kprobe, fops); +Here, we need to set up
kprobe_ctlblkand some ofpt_regsmembers, ip, cs andorig_axas optimized_callback()@arch/x86/kernel/kprobes.c does.Quoted 4 lines
I'm curious to what this is used for? It doesn't seem to be needed for the generic kprobes. Because we know the probe was on a nop, there's no need to simulate the operation. IOW, there's no need for
singlestep()or other gdb like operations.
Quoted 5 lines
It is needed to handle recursion, for instance. If in the rare case a kprobe handler calls another routine which also has a kprobe installed (and so on), we just bypass calling the 2nd kprobe's handlers. To do this and to set back the original kprobe context, we track the kprobe state in the
per_cpukprobe_ctlblk.
OK, so this looks a bit more involved. I'll look into this as well. This is still all under RFC now anyway. But I think it is doable.
Thanks!
-- Steve
Hi Steven,
Thanks for this nice feature!
Quoted 10 lines · Steven Rostedt
Hi All,
I started working on adding the -mfentry switch to ftrace, which allows us to remove the frame pointers requirement from function tracing as well as makes mcount (fentry) work just better.
But when I did this in another branch, I noticed that I broke kprobes in its most common usage. The attaching a probe at the beginning of a function to use get to its parameters.
Quoted 7 lines
So I started this branch. This branch is to have kprobes use ftrace directly when a probe is attached to a ftrace nop. Currently, kprobes will just error when that happens. With this patch set, it will hook into the ftrace infrastructure and use ftrace instead. This is more like an optimized probe as no breakpoints need to be set. A call to the function is done directly via the mcount trampoline. If ftrace
pt_regsis implemented for an arch, kprobes gets this feature for free.
I agreed this idea, this looks good to me too :) With -fentry, this can improve dynamic trace events very much.
BTW (OT), it seems that current kprobe data structure becomes a bit fat. Maybe what we need is just a "holder of hooking handler" as what ftrace provides, not a full storage data structure of copied instrucutions. Perhaps, we'd better diet the kprobe structure for transparency of hooking infrastructure.
Quoted 7 lines
The first patch is just a clean up that I need to push out to get rid of the annoying compile warning about initialized variables that gcc can't tell have been initialized.
The next two patches have ftrace pass both the
ftrace_opsstructure and thept_regsto the callback function that is registered with ftrace.
Quoted 6 lines
The last two patches have kprobes interact with ftrace and use the ftrace infrastructure instead.
I only did this for
x86_64, and will do it forx86_32and PPC64 if everyone agrees with this approach. Then I could find people to do it for other archs :)
OK, I'll review this soon!
Thank you!
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerQuoted 23 lines · Masami Hiramatsu
Hi Steven,
Thanks for this nice feature!
Quoted 10 lines · Steven Rostedt
Hi All,
I started working on adding the -mfentry switch to ftrace, which allows us to remove the frame pointers requirement from function tracing as well as makes mcount (fentry) work just better.
But when I did this in another branch, I noticed that I broke kprobes in its most common usage. The attaching a probe at the beginning of a function to use get to its parameters.
Quoted 7 lines
So I started this branch. This branch is to have kprobes use ftrace directly when a probe is attached to a ftrace nop. Currently, kprobes will just error when that happens. With this patch set, it will hook into the ftrace infrastructure and use ftrace instead. This is more like an optimized probe as no breakpoints need to be set. A call to the function is done directly via the mcount trampoline. If ftrace
pt_regsis implemented for an arch, kprobes gets this feature for free.
Quoted 8 lines
I agreed this idea, this looks good to me too :) With -fentry, this can improve dynamic trace events very much.
BTW (OT), it seems that current kprobe data structure becomes a bit fat. Maybe what we need is just a "holder of hooking handler" as what ftrace provides, not a full storage data structure of copied instrucutions. Perhaps, we'd better diet the kprobe structure for transparency of hooking infrastructure.
Sure, I can make the ftrace_ops field in kprobes dynamically allocated instead. That shouldn't be an issue.
Quoted 8 lines
Quoted 8 lines
The first patch is just a clean up that I need to push out to get rid of the annoying compile warning about initialized variables that gcc can't tell have been initialized.
The next two patches have ftrace pass both the
ftrace_opsstructure and thept_regsto the callback function that is registered with ftrace.
Quoted 8 lines
Quoted 6 lines
The last two patches have kprobes interact with ftrace and use the ftrace infrastructure instead.
I only did this for
x86_64, and will do it forx86_32and PPC64 if everyone agrees with this approach. Then I could find people to do it for other archs :)OK, I'll review this soon!
Thanks!
-- Steve
Quoted 27 lines · Steven Rostedt
Quoted 26 lines · Masami Hiramatsu
Hi Steven,
Thanks for this nice feature!
Quoted 10 lines · Steven Rostedt
Hi All,
I started working on adding the -mfentry switch to ftrace, which allows us to remove the frame pointers requirement from function tracing as well as makes mcount (fentry) work just better.
But when I did this in another branch, I noticed that I broke kprobes in its most common usage. The attaching a probe at the beginning of a function to use get to its parameters.
Quoted 7 lines
So I started this branch. This branch is to have kprobes use ftrace directly when a probe is attached to a ftrace nop. Currently, kprobes will just error when that happens. With this patch set, it will hook into the ftrace infrastructure and use ftrace instead. This is more like an optimized probe as no breakpoints need to be set. A call to the function is done directly via the mcount trampoline. If ftrace
pt_regsis implemented for an arch, kprobes gets this feature for free.I agreed this idea, this looks good to me too :) With -fentry, this can improve dynamic trace events very much.
Quoted 8 lines
Quoted 5 lines
BTW (OT), it seems that current kprobe data structure becomes a bit fat. Maybe what we need is just a "holder of hooking handler" as what ftrace provides, not a full storage data structure of copied instrucutions. Perhaps, we'd better diet the kprobe structure for transparency of hooking infrastructure.
Sure, I can make the
ftrace_opsfield in kprobes dynamically allocated instead. That shouldn't be an issue.
By the way (again), perhaps, much simpler solution is using ftrace not in kprobe, but in the trace_kprobe. Of course, there are several pros and cons...
The pros:
- Arch independent solution (anyway, ftrace still needs passing pt_regs to their handler)
- Don't need to introduce more complexity into kprobes itself.
- Maybe systemtap also can catch up with this as using same method.
The cons:
- Native kprobes users will be disappointed... anyway, they just need to move their probes to the next instruction (usually addr+=5 is OK).
... are there any other cons? :)
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerQuoted 41 lines · Masami Hiramatsu
Quoted 27 lines · Steven Rostedt
Quoted 26 lines · Masami Hiramatsu
Hi Steven,
Thanks for this nice feature!
Quoted 10 lines · Steven Rostedt
Hi All,
I started working on adding the -mfentry switch to ftrace, which allows us to remove the frame pointers requirement from function tracing as well as makes mcount (fentry) work just better.
But when I did this in another branch, I noticed that I broke kprobes in its most common usage. The attaching a probe at the beginning of a function to use get to its parameters.
Quoted 7 lines
So I started this branch. This branch is to have kprobes use ftrace directly when a probe is attached to a ftrace nop. Currently, kprobes will just error when that happens. With this patch set, it will hook into the ftrace infrastructure and use ftrace instead. This is more like an optimized probe as no breakpoints need to be set. A call to the function is done directly via the mcount trampoline. If ftrace
pt_regsis implemented for an arch, kprobes gets this feature for free.I agreed this idea, this looks good to me too :) With -fentry, this can improve dynamic trace events very much.
Quoted 8 lines
Quoted 5 lines
BTW (OT), it seems that current kprobe data structure becomes a bit fat. Maybe what we need is just a "holder of hooking handler" as what ftrace provides, not a full storage data structure of copied instrucutions. Perhaps, we'd better diet the kprobe structure for transparency of hooking infrastructure.
Sure, I can make the
ftrace_opsfield in kprobes dynamically allocated instead. That shouldn't be an issue.By the way (again), perhaps, much simpler solution is using ftrace not in kprobe, but in the
trace_kprobe. Of course, there are several pros and cons...
Quoted 5 lines
The pros:
- Arch independent solution (anyway, ftrace still needs passingpt_regsto their handler)
- Don't need to introduce more complexity into kprobes itself.
- Maybe systemtap also can catch up with this as using same method.
Note that systemtap and others will be hooking into kprobes version, not the trace_kprobe one. If we do it in trace_kprobe, then everyone else needs to reimplement it too. I have bigger ideas for the future of this, and I really want to get this working. If it doesn't work for kprobes, then it won't work for anything else.
Quoted 4 lines
The cons:
- Native kprobes users will be disappointed... anyway, they just need to move their probes to the next instruction (usually addr+=5 is OK).
I've been told that doing the addr+=5 (which is also arch specific) can break things for other tools.
-- Steve
Quoted 6 lines
... are there any other cons? :)
Thank you,
Quoted 48 lines · Steven Rostedt
Quoted 41 lines · Masami Hiramatsu
Quoted 27 lines · Steven Rostedt
Quoted 26 lines · Masami Hiramatsu
Hi Steven,
Thanks for this nice feature!
Quoted 10 lines · Steven Rostedt
Hi All,
I started working on adding the -mfentry switch to ftrace, which allows us to remove the frame pointers requirement from function tracing as well as makes mcount (fentry) work just better.
But when I did this in another branch, I noticed that I broke kprobes in its most common usage. The attaching a probe at the beginning of a function to use get to its parameters.
Quoted 7 lines
So I started this branch. This branch is to have kprobes use ftrace directly when a probe is attached to a ftrace nop. Currently, kprobes will just error when that happens. With this patch set, it will hook into the ftrace infrastructure and use ftrace instead. This is more like an optimized probe as no breakpoints need to be set. A call to the function is done directly via the mcount trampoline. If ftrace
pt_regsis implemented for an arch, kprobes gets this feature for free.I agreed this idea, this looks good to me too :) With -fentry, this can improve dynamic trace events very much.
Quoted 8 lines
Quoted 5 lines
BTW (OT), it seems that current kprobe data structure becomes a bit fat. Maybe what we need is just a "holder of hooking handler" as what ftrace provides, not a full storage data structure of copied instrucutions. Perhaps, we'd better diet the kprobe structure for transparency of hooking infrastructure.
Sure, I can make the
ftrace_opsfield in kprobes dynamically allocated instead. That shouldn't be an issue.By the way (again), perhaps, much simpler solution is using ftrace not in kprobe, but in the
trace_kprobe. Of course, there are several pros and cons...Quoted 5 lines
The pros:
- Arch independent solution (anyway, ftrace still needs passingpt_regsto their handler)
- Don't need to introduce more complexity into kprobes itself.
- Maybe systemtap also can catch up with this as using same method.
Quoted 5 lines
Note that systemtap and others will be hooking into kprobes version, not the
trace_kprobeone. If we do it intrace_kprobe, then everyone else needs to reimplement it too. I have bigger ideas for the future of this, and I really want to get this working. If it doesn't work for kprobes, then it won't work for anything else.
I don't think it won't work. It can work but on a long way. Could you tell me your "bigger ideas"? Perhaps, we are on the different way but aim to same goal.
Quoted 6 lines
Quoted 3 lines
The cons:
- Native kprobes users will be disappointed... anyway, they just need to move their probes to the next instruction (usually addr+=5 is OK).I've been told that doing the addr+=5 (which is also arch specific) can break things for other tools.
As I told in previous mail, I think kprobes can do that transparently.
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerQuoted 3 lines · Masami Hiramatsu
I don't think it won't work. It can work but on a long way. Could you tell me your "bigger ideas"? Perhaps, we are on the different way but aim to same goal.
Part of the bigger ideas is to have things like function graph tracing use this, as it will simplify the entry.S code. There's other things that may come out of this too.
Quoted 9 lines
Quoted 7 lines
Quoted 4 lines
The cons:
- Native kprobes users will be disappointed... anyway, they just need to move their probes to the next instruction (usually addr+=5 is OK).I've been told that doing the addr+=5 (which is also arch specific) can break things for other tools.
As I told in previous mail, I think kprobes can do that transparently.
Yeah, it could, but I'm afraid this may need to be done differently for every arch. If I'm working on getting this code to work for ftrace, which will require modifying ever arch as well, kprobes can get the changes for free.
-- Steve
Quoted 9 lines · Steven Rostedt
Quoted 3 lines · Masami Hiramatsu
I don't think it won't work. It can work but on a long way. Could you tell me your "bigger ideas"? Perhaps, we are on the different way but aim to same goal.
Part of the bigger ideas is to have things like function graph tracing use this, as it will simplify the
entry.Scode. There's other things that may come out of this too.
Hmm, I think that the current function graph tracing implementation is more scalable than kretprobes, because kretprobe requires spinlock on every hit. Moreover, you can't probe NMI handler with kprobe, and kprobes on irq-handler are also possible to fail because of recursive-call.
So I don't recommend using kretprobe for function-graph tracer :-(
However, even though, some parts of code can be shared among them and it will simplify their implementations.
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
Quoted 3 lines
The cons:
- Native kprobes users will be disappointed... anyway, they just need to move their probes to the next instruction (usually addr+=5 is OK).I've been told that doing the addr+=5 (which is also arch specific) can break things for other tools.
Quoted 6 lines
Quoted 1 line
As I told in previous mail, I think kprobes can do that transparently.
Yeah, it could, but I'm afraid this may need to be done differently for every arch. If I'm working on getting this code to work for ftrace, which will require modifying ever arch as well, kprobes can get the changes for free.
I guess that anyway it should be done (at least, carefully checked) for every arch.
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerQuoted 11 lines · Masami Hiramatsu
Quoted 9 lines · Steven Rostedt
Quoted 3 lines · Masami Hiramatsu
I don't think it won't work. It can work but on a long way. Could you tell me your "bigger ideas"? Perhaps, we are on the different way but aim to same goal.
Part of the bigger ideas is to have things like function graph tracing use this, as it will simplify the
entry.Scode. There's other things that may come out of this too.
Quoted 6 lines
Hmm, I think that the current function graph tracing implementation is more scalable than kretprobes, because kretprobe requires spinlock on every hit. Moreover, you can't probe NMI handler with kprobe, and kprobes on irq-handler are also possible to fail because of recursive-call.
So I don't recommend using kretprobe for function-graph tracer :-(
Sorry for the confusion. My idea is not to use kretprobe with function graph tracer, but to use the ftrace hooks with the pt_regs and friends for function graph tracer instead of what it does today, which is to add function graph code directly into entry.S.
The point I was making is, if I need to get ftrace function tracing being good enough for function graph tracer, then it should work with kprobes without any issues. If I need to do the work anyway (for function graph tracing) then why not use it directly with kprobes instead of doing more hooks just in the kprobe_trace?
-- Steve
Quoted 19 lines · Steven Rostedt
Quoted 11 lines · Masami Hiramatsu
Quoted 9 lines · Steven Rostedt
Quoted 3 lines · Masami Hiramatsu
I don't think it won't work. It can work but on a long way. Could you tell me your "bigger ideas"? Perhaps, we are on the different way but aim to same goal.
Part of the bigger ideas is to have things like function graph tracing use this, as it will simplify the
entry.Scode. There's other things that may come out of this too.Quoted 6 lines
Hmm, I think that the current function graph tracing implementation is more scalable than kretprobes, because kretprobe requires spinlock on every hit. Moreover, you can't probe NMI handler with kprobe, and kprobes on irq-handler are also possible to fail because of recursive-call.
So I don't recommend using kretprobe for function-graph tracer :-(
Quoted 4 lines
Sorry for the confusion. My idea is not to use kretprobe with function graph tracer, but to use the ftrace hooks with the
pt_regsand friends for function graph tracer instead of what it does today, which is to add function graph code directly intoentry.S.
Ah, OK.
Quoted 3 lines
The point I was making is, if I need to get ftrace function tracing being good enough for function graph tracer, then it should work with kprobes without any issues.
No, I don't think so, because kprobes user may trace a flags register or segment registers. However, function graph tracer only needs stack register etc. Thus, if ftrace function tracing is good enough for kprobes handlers, it is enough for function graph tracer too.
Quoted 5 lines
If I need to do the work anyway (for
function graph tracing) then why not use it directly with kprobes instead of doing more hooks just in thekprobe_trace?From the kprobe-tracer point of view, I don't mind. I just care
about complexity, and compatibility of kprobe handlers.
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerQuoted 8 lines · Masami Hiramatsu
Quoted 3 lines
The point I was making is, if I need to get ftrace function tracing being good enough for function graph tracer, then it should work with kprobes without any issues.
No, I don't think so, because kprobes user may trace a flags register or segment registers. However, function graph tracer only needs stack register etc. Thus, if ftrace function tracing is good enough for kprobes handlers, it is enough for function graph tracer too.
The added code needed for ftrace is not much more. We just need to save all of pt_regs and that should work (I already save most of it). The flags can be saved, but things like compare flags will be useless, as those are used. But compare flags are undefined when calling a function anyway.
Quoted 7 lines
Quoted 6 lines
If I need to do the work anyway (for
function graph tracing) then why not use it directly with kprobes instead of doing more hooks just in thekprobe_trace?From the kprobe-tracer point of view, I don't mind. I just care
about complexity, and compatibility of kprobe handlers.
Right, so far there's not much changes to the kprobe side. I'll see if I can make ftrace do all the hard work to get the proper registers. I want to make as much as possible stay in the generic kprobe code, and not touch the arch code. But I may still need to do something like 'increment rip' or whatever.
Note, we will need to touch kprobes one way or another. Either we have kprobes hook to ftrace, or we need to do the nop skip trick, which will probably be as intrusive in the kprobe code.
Thanks!
-- Steve
Quoted 11 lines · Steven Rostedt
Quoted 8 lines · Masami Hiramatsu
Quoted 3 lines
The point I was making is, if I need to get ftrace function tracing being good enough for function graph tracer, then it should work with kprobes without any issues.
No, I don't think so, because kprobes user may trace a flags register or segment registers. However, function graph tracer only needs stack register etc. Thus, if ftrace function tracing is good enough for kprobes handlers, it is enough for function graph tracer too.
Quoted 5 lines
The added code needed for ftrace is not much more. We just need to save all of
pt_regsand that should work (I already save most of it). The flags can be saved, but things like compare flags will be useless, as those are used. But compare flags are undefined when calling a function anyway.
Agreed. I think users may just want to see other status flags.
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
If I need to do the work anyway (for
function graph tracing) then why not use it directly with kprobes instead of doing more hooks just in thekprobe_trace?
Quoted 8 lines
Quoted 2 lines
Quoted 1 line
From the kprobe-tracer point of view, I don't mind. I just care
about complexity, and compatibility of kprobe handlers.
Right, so far there's not much changes to the kprobe side. I'll see if I can make ftrace do all the hard work to get the proper registers. I want to make as much as possible stay in the generic kprobe code, and not touch the arch code. But I may still need to do something like 'increment rip' or whatever.
kprobes arch side code is not so complex, it has less states. Generic kprobes code has much more states to support module probes, module init, aggregated probes, and so on. So it is OK for me to touch the arch code :).
Quoted 3 lines
Note, we will need to touch kprobes one way or another. Either we have kprobes hook to ftrace, or we need to do the nop skip trick, which will probably be as intrusive in the kprobe code.
I see. OK, I'm now looking forward to your work ;)
Thank you!
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerQuoted 1 line · Masami Hiramatsu
I see. OK, I'm now looking forward to your work ;)
Hi Masami,
BTW, do you have any test suits that I could use to test the changes I make. Something that I may be able to catch regressions with?
Thanks!
-- Steve
Quoted 8 lines · Steven Rostedt
Quoted 1 line · Masami Hiramatsu
I see. OK, I'm now looking forward to your work ;)
Hi Masami,
BTW, do you have any test suits that I could use to test the changes I make. Something that I may be able to catch regressions with?
Yes, here are the test to ensure putting probes on module/module init code.
Also, basic smoke test is already in the kernel.
BTW, I think we may need more testcases for checking registers etc.
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]