ftrace: More stuff for 3.19
Subsystems (5)
Steven Rostedt
maintainercover ftrace: More stuff for 3.19
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
for-next
Head SHA1: 62a207d748dd9224140a634786b274fdb6ece0b9
Masami Hiramatsu (3):
kprobes/ftrace: Recover original IP if pre_handler doesn't change it ftrace, kprobes: Support IPMODIFY flag to find IP modify conflict
kprobes: Add IPMODIFY flag to kprobe_ftrace_ops
Steven Rostedt (Red Hat) (2):
tracing/trivial: Fix typos and make an int into a bool ftrace/x86: Have static function tracing always test for function graph
----
Documentation/trace/ftrace.txt | 5 ++ arch/x86/kernel/kprobes/ftrace.c | 9 ++- arch/x86/kernel/mcount_64.S | 3 +- include/linux/ftrace.h | 16 ++++- kernel/kprobes.c | 2 +- kernel/trace/ftrace.c | 144 ++++++++++++++++++++++++++++++++++++++- kernel/trace/trace_functions.c | 6 +- 7 files changed, 172 insertions(+), 13 deletions(-)
Steven Rostedt
maintainerPATCH 1/5 tracing/trivial: Fix typos and make an int into a bool
From: "Steven Rostedt (Red Hat)" <[email protected]>
Fix up a few typos in comments and convert an int into a bool in update_traceon_count().
--- kernel/trace/ftrace.c | 2 +- kernel/trace/trace_functions.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-)
kernel/trace/ftrace.c +1 -1
@@ -1119,7 +1119,7 @@ static struct ftrace_ops global_ops = {/* * This is used by __kernel_text_address() to return true if the -* the address is on a dynamically allocated trampoline that would +* address is on a dynamically allocated trampoline that would * not return true for either core_kernel_text() or * is_module_text_address(). */
kernel/trace/trace_functions.c +3 -3
@@ -261,14 +261,14 @@ static struct tracer function_trace __tracer_data = };#ifdef CONFIG_DYNAMIC_FTRACE -static void update_traceon_count (void **data,int on) +static void update_traceon_count (void **data,bool on) {long *count = (long *)data;long old_count = *count;/* * Tracing gets disabled (or enabled) once per count. -* This function can be called at the same time on mulitple CPUs. +* This function can be called at the same time on multiple CPUs. * It is fine if both disable (or enable) tracing, as disabling * (or enabling) the second time doesn't do anything as the * state of the tracer is already disabled (or enabled).
@@ -288,7 +288,7 @@ static void update_traceon_count(void **data, int on)* the new state is visible before changing the counter by * one minus the old counter. This guarantees that another CPU * executing this code will see the new state before seeing -* the new counter value, and would not do anthing if the new +* the new counter value, and would not do anything if the new * counter is seen. * * Note, there is no synchronization between this and a user
Signature · 1 line
2.1.1
Steven Rostedt
maintainerPATCH 2/5 kprobes/ftrace: Recover original IP if pre_handler doesnt change it
In reply to Steven RostedtFrom: Masami Hiramatsu <[email protected]>
Recover original IP register if the pre_handler doesn't change it. Since current kprobes doesn't expect that another ftrace handler may change regs->ip, it sets kprobe.addr + MCOUNT_INSN_SIZE to regs->ip and returns to ftrace.
This seems wrong behavior since kprobes can recover regs->ip and safely pass it to another handler.
This adds code which recovers original regs->ip passed from ftrace right before returning to ftrace, so that another ftrace user can change regs->ip.
--- arch/x86/kernel/kprobes/ftrace.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
arch/x86/kernel/kprobes/ftrace.c +6 -3
@@ -27,7 +27,7 @@static nokprobe_inline int __skip_singlestep(struct kprobe *p, struct pt_regs *regs, -struct kprobe_ctlblk *kcb) +struct kprobe_ctlblk *kcb,unsigned long orig_ip) {/* * Emulate singlestep (and also recover regs->ip)
@@ -39,6 +39,8 @@ int __skip_singlestep(struct kprobe *p, struct pt_regs *regs, p->post_handler (p, regs,0 ); }__this_cpu_write (current_kprobe,NULL ); +if (orig_ip) + regs->ip = orig_ip;return 1 ; }
@@ -46,7 +48,7 @@ int skip_singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) {if (kprobe_ftrace (p)) -return __skip_singlestep (p, regs, kcb); +return __skip_singlestep (p, regs, kcb,0 );else return 0 ; }
@@ -71,13 +73,14 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,if (kprobe_running ()) {kprobes_inc_nmissed_count (p); }else { +unsigned long orig_ip = regs->ip;/* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */ regs->ip = ip +sizeof (kprobe_opcode_t);__this_cpu_write (current_kprobe, p); kcb->kprobe_status =KPROBE_HIT_ACTIVE ;if (!p->pre_handler || !p->pre_handler (p, regs)) -__skip_singlestep (p, regs, kcb); +__skip_singlestep (p, regs, kcb, orig_ip);/* * If pre_handler returns !0, it sets regs->ip and * resets current kprobe.
Signature · 1 line
2.1.1
Steven Rostedt
maintainerPATCH 3/5 ftrace, kprobes: Support IPMODIFY flag to find IP modify conflict
In reply to Steven RostedtFrom: Masami Hiramatsu <[email protected]>
Introduce FTRACE_OPS_FL_IPMODIFY to avoid conflict among ftrace users who may modify regs->ip to change the execution path. If two or more users modify the regs->ip on the same function entry, one of them will be broken. So they must add IPMODIFY flag and make sure that ftrace_set_filter_ip() succeeds.
Note that ftrace doesn't allow ftrace_ops which has IPMODIFY flag to have notrace hash, and the ftrace_ops must have a filter hash (so that the ftrace_ops can hook only specific entries), because it strongly depends on the address and must be allowed for only few selected functions.
--- Documentation/trace/ftrace.txt | 5 ++ include/linux/ftrace.h | 16 ++++- kernel/trace/ftrace.c | 142 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 159 insertions(+), 4 deletions(-)
Documentation/trace/ftrace.txt +5 -0
@@ -234,6 +234,11 @@ of ftrace. Here is a list of some of the key files: will be displayed on the same line as the function that is returning registers. + If the callback registered to be traced by a function with + the "ip modify" attribute (thus the regs->ip can be changed), + an 'I' will be displayed on the same line as the function that + can be overridden. + function_profile_enabled: When set it will enable all functions with either the function
include/linux/ftrace.h +14 -2
@@ -61,6 +61,11 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops);/* * FTRACE_OPS_FL_* bits denote the state of ftrace_ops struct and are * set in the flags member. +* CONTROL, SAVE_REGS, SAVE_REGS_IF_SUPPORTED, RECURSION_SAFE, STUB and +* IPMODIFY are a kind of attribute flags which can be set only before +* registering the ftrace_ops, and can not be modified while registered. +* Changing those attribute flags after regsitering ftrace_ops will +* cause unexpected results. * * ENABLED - set/unset when ftrace_ops is registered/unregistered * DYNAMIC - set when ftrace_ops is registered to denote dynamically
@@ -101,6 +106,10 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops);* The ftrace_ops trampoline can be set by the ftrace users, and * in such cases the arch must not modify it. Only the arch ftrace * core code should set this flag. +* IPMODIFY - The ops can modify the IP register. This can only be set with +* SAVE_REGS. If another ops with this flag set is already registered +* for any of the functions that this ops will be registered for, then +* this ops will fail to register or set_filter_ip. */ enum {FTRACE_OPS_FL_ENABLED =1 <<0 ,
@@ -116,6 +125,7 @@ enum {FTRACE_OPS_FL_REMOVING =1 <<10 ,FTRACE_OPS_FL_MODIFYING =1 <<11 ,FTRACE_OPS_FL_ALLOC_TRAMP =1 <<12 , + FTRACE_OPS_FL_IPMODIFY = 1 << 13, };#ifdef CONFIG_DYNAMIC_FTRACE
@@ -310,6 +320,7 @@ bool is_ftrace_trampoline(unsigned long addr);* ENABLED - the function is being traced * REGS - the record wants the function to save regs * REGS_EN - the function is set up to save regs. +* IPMODIFY - the record allows for the IP address to be changed. * * When a new ftrace_ops is registered and wants a function to save * pt_regs, the rec->flag REGS is set. When the function has been
@@ -323,10 +334,11 @@ enum {FTRACE_FL_REGS_EN = (1UL <<29 ),FTRACE_FL_TRAMP = (1UL <<28 ),FTRACE_FL_TRAMP_EN = (1UL <<27 ), + FTRACE_FL_IPMODIFY = (1UL << 26), }; -#define FTRACE_REF_MAX_SHIFT 27 -#define FTRACE_FL_BITS 5 +#define FTRACE_REF_MAX_SHIFT 26 +#define FTRACE_FL_BITS 6#define FTRACE_FL_MASKED_BITS ((1UL << FTRACE_FL_BITS) - 1)#define FTRACE_FL_MASK (FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT)#define FTRACE_REF_MAX ((1UL << FTRACE_REF_MAX_SHIFT) - 1)
kernel/trace/ftrace.c +140 -2
187 lines not on this page · raw message
Signature · 1 line
2.1.1
Steven Rostedt
maintainerPATCH 4/5 kprobes: Add IPMODIFY flag to kprobe_ftrace_ops
In reply to Steven RostedtFrom: Masami Hiramatsu <[email protected]>
Add FTRACE_OPS_FL_IPMODIFY flag to kprobe_ftrace_ops since kprobes can changes regs->ip.
--- kernel/kprobes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/kprobes.c +1 -1
@@ -915,7 +915,7 @@ static struct kprobe *alloc_aggr_kprobe(struct kprobe *p)#ifdef CONFIG_KPROBES_ON_FTRACE static struct ftrace_ops kprobe_ftrace_ops__read_mostly = { .func = kprobe_ftrace_handler, - .flags =FTRACE_OPS_FL_SAVE_REGS , + .flags =FTRACE_OPS_FL_SAVE_REGS |FTRACE_OPS_FL_IPMODIFY , };static int kprobe_ftrace_enabled;
Signature · 1 line
2.1.1
Steven Rostedt
maintainerPATCH 5/5 ftrace/x86: Have static function tracing always test for function graph
In reply to Steven RostedtFrom: "Steven Rostedt (Red Hat)" <[email protected]>
New updates to the ftrace generic code had ftrace_stub not always being called when ftrace is off. This causes the static tracer to always save and restore functions. But it also showed that when function tracing is running, the function graph tracer can not. We should always check to see if function graph tracing is running even if the function tracer is running too. The function tracer code is not the only one that uses the hook to function mcount.
--- arch/x86/kernel/mcount_64.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/x86/kernel/mcount_64.S +2 -1
@@ -194,6 +194,7 @@ ENTRY(function_hook) cmpq $ftrace_stub, ftrace_trace_function jnz trace +fgraph_trace: #ifdef CONFIG_FUNCTION_GRAPH_TRACER cmpq $ftrace_stub, ftrace_graph_return jnz ftrace_graph_caller
@@ -220,7 +221,7 @@ trace: MCOUNT_RESTORE_FRAME - jmp ftrace_stub + jmp fgraph_trace END(function_hook) #endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_FUNCTION_TRACER */
Signature · 1 line
2.1.1