tracing/kprobes: Dynamic events on module support
Subsystems (4)
cover tracing/kprobes: Dynamic events on module support
Hi Steven,
Here, I'd like to push updates of dynamic events and perf-probe for supporting dynamic events on module.
The main part of this series is 1-5th patches for kprobes and dynamic event tracer, which allows us to add events on offline kernel module. This means we can put events even on the init functions of the drivers before loading. The requirement of this feature comes from my recent experience of a driver debugging. It had a timing bug in the initialization routine, and it was hard to catch them without tracing the behavior.
I added some perf-probe updates (which including some resent patches), And it's OK to pull only the main part (kprobes and ftrace patches) without perf updates.
Thank you,
---
Masami Hiramatsu (13):
perf probe: Support adding probes on offline kernel modules perf probe: Add probed module in front of function [RESEND]perf probe: Introduce debuginfo to encapsulate dwarf information [RESEND]perf probe: Warn when more than two lines are given [RESEND][CLEANUP]perf-probe: Move dwarf library routines to dwarf-aux.{c,h} [RESEND][CLEANUP]perf probe: Remove redundant dwarf functions [RESEND][CLEANUP]perf probe: Move strtailcmp to string.c [RESEND][CLEANUP]perf probe: Rename DIE_FIND_CB_FOUND to DIE_FIND_CB_END tracing/kprobe: Update symbol reference when loading module tracing/kprobes: Support module init function probing
kprobes: Return -ENOENT if probe point doesn't exist [CLEANUP]tracing/kprobes: merge trace probe enable/disable functions [CLEANUP]tracing/kprobes: Rename probe_* to trace_probe_*
Documentation/trace/kprobetrace.txt | 9 kernel/kprobes.c | 33 + kernel/trace/trace_kprobe.c | 314 +++++++++---- tools/perf/Documentation/perf-probe.txt | 6 tools/perf/Makefile | 2 tools/perf/builtin-probe.c | 14 - tools/perf/util/dwarf-aux.c | 663 +++++++++++++++++++++++++++ tools/perf/util/dwarf-aux.h | 100 ++++ tools/perf/util/probe-event.c | 165 +++++-- tools/perf/util/probe-event.h | 1 tools/perf/util/probe-finder.c | 752 ++++--------------------------- tools/perf/util/probe-finder.h | 43 +- tools/perf/util/string.c | 19 + tools/perf/util/util.h | 1 14 files changed, 1304 insertions(+), 818 deletions(-) create mode 100644 tools/perf/util/dwarf-aux.c create mode 100644 tools/perf/util/dwarf-aux.h
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
PATCH 1/13 tracing/kprobes: Rename probe_* to trace_probe_*
Rename probe_* to trace_probe_* for avoiding namespace confliction. This also fixes improper names of find_probe_event() and cleanup_all_probes() to find_trace_probe() and release_all_trace_probes() respectively.
---
kernel/trace/trace_kprobe.c | 43 ++++++++++++++++++++++--------------------- 1 files changed, 22 insertions(+), 21 deletions(-)
kernel/trace/trace_kprobe.c +22 -21
@@ -555,12 +555,12 @@ struct trace_probe { (sizeof(struct probe_arg) * (n))) -static __kprobes int probe_is_return (struct trace_probe *tp) +static __kprobes int trace_probe_is_return (struct trace_probe *tp) {return tp->rp.handler !=NULL ; } -static __kprobes const char *probe_symbol (struct trace_probe *tp) +static __kprobes const char *trace_probe_symbol (struct trace_probe *tp) {return tp->symbol ? tp->symbol :"unknown" ; }
@@ -671,7 +671,7 @@ static void free_trace_probe(struct trace_probe *tp)kfree (tp); } -static struct trace_probe *find_probe_event (const char *event, +static struct trace_probe *find_trace_probe (const char *event,const char *group) {struct trace_probe *tp;
@@ -686,7 +686,7 @@ static struct trace_probe *find_probe_event(const char *event,/* Unregister a trace_probe and probe_event: call with locking probe_lock */ static void unregister_trace_probe (struct trace_probe *tp) { -if (probe_is_return (tp)) +if (trace_probe_is_return (tp))unregister_kretprobe (&tp->rp);else unregister_kprobe (&tp->rp.kp);
@@ -703,7 +703,7 @@ static int register_trace_probe(struct trace_probe *tp)mutex_lock (&probe_lock);/* register as an event */ - old_tp =find_probe_event (tp->call.name, tp->call.class->system); + old_tp =find_trace_probe (tp->call.name, tp->call.class->system);if (old_tp) {/* delete old event */ unregister_trace_probe (old_tp);
@@ -716,7 +716,7 @@ static int register_trace_probe(struct trace_probe *tp) } tp->rp.kp.flags |=KPROBE_FLAG_DISABLED ; -if (probe_is_return (tp)) +if (trace_probe_is_return (tp)) ret =register_kretprobe (&tp->rp);else ret =register_kprobe (&tp->rp.kp);
@@ -1025,7 +1025,7 @@ static int create_trace_probe(int argc, char **argv)return -EINVAL ; }mutex_lock (&probe_lock); - tp =find_probe_event (event, group); + tp =find_trace_probe (event, group);if (!tp) {mutex_unlock (&probe_lock);pr_info ("Event %s/%s doesn't exist.\n" , group, event);
@@ -1144,7 +1144,7 @@ error:return ret; } -static void cleanup_all_probes (void ) +static void release_all_trace_probes (void ) {struct trace_probe *tp;
@@ -1181,15 +1181,16 @@ static int probes_seq_show(struct seq_file *m, void *v)struct trace_probe *tp = v;int i; -seq_printf (m,"%c" ,probe_is_return (tp) ?'r' :'p' ); +seq_printf (m,"%c" ,trace_probe_is_return (tp) ?'r' :'p' );seq_printf (m,":%s/%s" , tp->call.class->system, tp->call.name);if (!tp->symbol)seq_printf (m," 0x%p" , tp->rp.kp.addr);else if (tp->rp.kp.offset) -seq_printf (m," %s+%u" ,probe_symbol (tp), tp->rp.kp.offset); +seq_printf (m," %s+%u" ,trace_probe_symbol (tp), + tp->rp.kp.offset);else -seq_printf (m," %s" ,probe_symbol (tp)); +seq_printf (m," %s" ,trace_probe_symbol (tp));for (i =0 ; i < tp->nr_args; i++)seq_printf (m," %s=%s" , tp->args[i].name, tp->args[i].comm);
@@ -1209,7 +1210,7 @@ static int probes_open(struct inode *inode, struct file *file) {if ((file->f_mode &FMODE_WRITE ) && (file->f_flags &O_TRUNC )) -cleanup_all_probes (); +release_all_trace_probes ();return seq_open (file, &probes_seq_op); }
@@ -1516,7 +1517,7 @@ static int probe_event_enable(struct ftrace_event_call *call)struct trace_probe *tp = (struct trace_probe *)call->data; tp->flags |=TP_FLAG_TRACE ; -if (probe_is_return (tp)) +if (trace_probe_is_return (tp))return enable_kretprobe (&tp->rp);else return enable_kprobe (&tp->rp.kp);
@@ -1528,7 +1529,7 @@ static void probe_event_disable(struct ftrace_event_call *call) tp->flags &= ~TP_FLAG_TRACE ;if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) { -if (probe_is_return (tp)) +if (trace_probe_is_return (tp))disable_kretprobe (&tp->rp);else disable_kprobe (&tp->rp.kp);
@@ -1596,7 +1597,7 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len)const char *fmt, *arg; -if (!probe_is_return (tp)) { +if (!trace_probe_is_return (tp)) { fmt ="(%lx)" ; arg ="REC->" FIELD_STRING_IP ; }else {
@@ -1720,7 +1721,7 @@ static int probe_perf_enable(struct ftrace_event_call *call) tp->flags |=TP_FLAG_PROFILE ; -if (probe_is_return (tp)) +if (trace_probe_is_return (tp))return enable_kretprobe (&tp->rp);else return enable_kprobe (&tp->rp.kp);
@@ -1733,7 +1734,7 @@ static void probe_perf_disable(struct ftrace_event_call *call) tp->flags &= ~TP_FLAG_PROFILE ;if (!(tp->flags &TP_FLAG_TRACE )) { -if (probe_is_return (tp)) +if (trace_probe_is_return (tp))disable_kretprobe (&tp->rp);else disable_kprobe (&tp->rp.kp);
@@ -1805,7 +1806,7 @@ static int register_probe_event(struct trace_probe *tp)/* Initialize ftrace_event_call */ INIT_LIST_HEAD (&call->class->fields); -if (probe_is_return (tp)) { +if (trace_probe_is_return (tp)) { call->event.funcs = &kretprobe_funcs; call->class->define_fields = kretprobe_event_define_fields; }else {
@@ -1897,7 +1898,7 @@ static __init int kprobe_trace_self_tests_init(void) warn++; }else {/* Enable trace point */ - tp =find_probe_event ("testprobe" ,KPROBE_EVENT_SYSTEM ); + tp =find_trace_probe ("testprobe" ,KPROBE_EVENT_SYSTEM );if (WARN_ON_ONCE (tp ==NULL )) {pr_warning ("error on getting new probe.\n" ); warn++;
@@ -1912,7 +1913,7 @@ static __init int kprobe_trace_self_tests_init(void) warn++; }else {/* Enable trace point */ - tp =find_probe_event ("testprobe2" ,KPROBE_EVENT_SYSTEM ); + tp =find_trace_probe ("testprobe2" ,KPROBE_EVENT_SYSTEM );if (WARN_ON_ONCE (tp ==NULL )) {pr_warning ("error on getting new probe.\n" ); warn++;
@@ -1938,7 +1939,7 @@ static __init int kprobe_trace_self_tests_init(void) } end: -cleanup_all_probes (); +release_all_trace_probes ();if (warn)pr_cont ("NG: Some tests are failed. Please check them.\n" );else
[tip:perf/core] tracing/kprobes: Rename probe_* to trace_probe_*
Commit-ID: 7143f168e2aa4bc7f8a8bcfe46d8dc52f7be869a Gitweb: http://git.kernel.org/tip/7143f168e2aa4bc7f8a8bcfe46d8dc52f7be869a Author: Masami Hiramatsu <[email protected]> AuthorDate: Mon, 27 Jun 2011 16:26:36 +0900 Committer: Steven Rostedt <[email protected]> CommitDate: Thu, 14 Jul 2011 17:44:43 -0400
tracing/kprobes: Rename probe_* to trace_probe_*
Rename probe_* to trace_probe_* for avoiding namespace confliction. This also fixes improper names of find_probe_event() and cleanup_all_probes() to find_trace_probe() and release_all_trace_probes() respectively.
--- kernel/trace/trace_kprobe.c | 43 ++++++++++++++++++++++--------------------- 1 files changed, 22 insertions(+), 21 deletions(-)
kernel/trace/trace_kprobe.c +22 -21
@@ -555,12 +555,12 @@ struct trace_probe { (sizeof(struct probe_arg) * (n))) -static __kprobes int probe_is_return (struct trace_probe *tp) +static __kprobes int trace_probe_is_return (struct trace_probe *tp) {return tp->rp.handler !=NULL ; } -static __kprobes const char *probe_symbol (struct trace_probe *tp) +static __kprobes const char *trace_probe_symbol (struct trace_probe *tp) {return tp->symbol ? tp->symbol :"unknown" ; }
@@ -671,7 +671,7 @@ static void free_trace_probe(struct trace_probe *tp)kfree (tp); } -static struct trace_probe *find_probe_event (const char *event, +static struct trace_probe *find_trace_probe (const char *event,const char *group) {struct trace_probe *tp;
@@ -686,7 +686,7 @@ static struct trace_probe *find_probe_event(const char *event,/* Unregister a trace_probe and probe_event: call with locking probe_lock */ static void unregister_trace_probe (struct trace_probe *tp) { -if (probe_is_return (tp)) +if (trace_probe_is_return (tp))unregister_kretprobe (&tp->rp);else unregister_kprobe (&tp->rp.kp);
@@ -703,7 +703,7 @@ static int register_trace_probe(struct trace_probe *tp)mutex_lock (&probe_lock);/* register as an event */ - old_tp =find_probe_event (tp->call.name, tp->call.class->system); + old_tp =find_trace_probe (tp->call.name, tp->call.class->system);if (old_tp) {/* delete old event */ unregister_trace_probe (old_tp);
@@ -716,7 +716,7 @@ static int register_trace_probe(struct trace_probe *tp) } tp->rp.kp.flags |=KPROBE_FLAG_DISABLED ; -if (probe_is_return (tp)) +if (trace_probe_is_return (tp)) ret =register_kretprobe (&tp->rp);else ret =register_kprobe (&tp->rp.kp);
@@ -1025,7 +1025,7 @@ static int create_trace_probe(int argc, char **argv)return -EINVAL ; }mutex_lock (&probe_lock); - tp =find_probe_event (event, group); + tp =find_trace_probe (event, group);if (!tp) {mutex_unlock (&probe_lock);pr_info ("Event %s/%s doesn't exist.\n" , group, event);
@@ -1144,7 +1144,7 @@ error:return ret; } -static void cleanup_all_probes (void ) +static void release_all_trace_probes (void ) {struct trace_probe *tp;
@@ -1181,15 +1181,16 @@ static int probes_seq_show(struct seq_file *m, void *v)struct trace_probe *tp = v;int i; -seq_printf (m,"%c" ,probe_is_return (tp) ?'r' :'p' ); +seq_printf (m,"%c" ,trace_probe_is_return (tp) ?'r' :'p' );seq_printf (m,":%s/%s" , tp->call.class->system, tp->call.name);if (!tp->symbol)seq_printf (m," 0x%p" , tp->rp.kp.addr);else if (tp->rp.kp.offset) -seq_printf (m," %s+%u" ,probe_symbol (tp), tp->rp.kp.offset); +seq_printf (m," %s+%u" ,trace_probe_symbol (tp), + tp->rp.kp.offset);else -seq_printf (m," %s" ,probe_symbol (tp)); +seq_printf (m," %s" ,trace_probe_symbol (tp));for (i =0 ; i < tp->nr_args; i++)seq_printf (m," %s=%s" , tp->args[i].name, tp->args[i].comm);
@@ -1209,7 +1210,7 @@ static int probes_open(struct inode *inode, struct file *file) {if ((file->f_mode &FMODE_WRITE ) && (file->f_flags &O_TRUNC )) -cleanup_all_probes (); +release_all_trace_probes ();return seq_open (file, &probes_seq_op); }
@@ -1518,7 +1519,7 @@ static int probe_event_enable(struct ftrace_event_call *call)struct trace_probe *tp = (struct trace_probe *)call->data; tp->flags |=TP_FLAG_TRACE ; -if (probe_is_return (tp)) +if (trace_probe_is_return (tp))return enable_kretprobe (&tp->rp);else return enable_kprobe (&tp->rp.kp);
@@ -1530,7 +1531,7 @@ static void probe_event_disable(struct ftrace_event_call *call) tp->flags &= ~TP_FLAG_TRACE ;if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) { -if (probe_is_return (tp)) +if (trace_probe_is_return (tp))disable_kretprobe (&tp->rp);else disable_kprobe (&tp->rp.kp);
@@ -1598,7 +1599,7 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len)const char *fmt, *arg; -if (!probe_is_return (tp)) { +if (!trace_probe_is_return (tp)) { fmt ="(%lx)" ; arg ="REC->" FIELD_STRING_IP ; }else {
@@ -1722,7 +1723,7 @@ static int probe_perf_enable(struct ftrace_event_call *call) tp->flags |=TP_FLAG_PROFILE ; -if (probe_is_return (tp)) +if (trace_probe_is_return (tp))return enable_kretprobe (&tp->rp);else return enable_kprobe (&tp->rp.kp);
@@ -1735,7 +1736,7 @@ static void probe_perf_disable(struct ftrace_event_call *call) tp->flags &= ~TP_FLAG_PROFILE ;if (!(tp->flags &TP_FLAG_TRACE )) { -if (probe_is_return (tp)) +if (trace_probe_is_return (tp))disable_kretprobe (&tp->rp);else disable_kprobe (&tp->rp.kp);
@@ -1807,7 +1808,7 @@ static int register_probe_event(struct trace_probe *tp)/* Initialize ftrace_event_call */ INIT_LIST_HEAD (&call->class->fields); -if (probe_is_return (tp)) { +if (trace_probe_is_return (tp)) { call->event.funcs = &kretprobe_funcs; call->class->define_fields = kretprobe_event_define_fields; }else {
@@ -1899,7 +1900,7 @@ static __init int kprobe_trace_self_tests_init(void) warn++; }else {/* Enable trace point */ - tp =find_probe_event ("testprobe" ,KPROBE_EVENT_SYSTEM ); + tp =find_trace_probe ("testprobe" ,KPROBE_EVENT_SYSTEM );if (WARN_ON_ONCE (tp ==NULL )) {pr_warning ("error on getting new probe.\n" ); warn++;
@@ -1914,7 +1915,7 @@ static __init int kprobe_trace_self_tests_init(void) warn++; }else {/* Enable trace point */ - tp =find_probe_event ("testprobe2" ,KPROBE_EVENT_SYSTEM ); + tp =find_trace_probe ("testprobe2" ,KPROBE_EVENT_SYSTEM );if (WARN_ON_ONCE (tp ==NULL )) {pr_warning ("error on getting new probe.\n" ); warn++;
@@ -1940,7 +1941,7 @@ static __init int kprobe_trace_self_tests_init(void) } end: -cleanup_all_probes (); +release_all_trace_probes ();if (warn)pr_cont ("NG: Some tests are failed. Please check them.\n" );else
PATCH 2/13 tracing/kprobes: merge trace probe enable/disable functions
In reply to Masami HiramatsuMerge redundant enable/disable functions into enable_trace_probe() and disable_trace_probe().
---
kernel/trace/trace_kprobe.c | 88 +++++++++++++++++-------------------------- 1 files changed, 34 insertions(+), 54 deletions(-)
kernel/trace/trace_kprobe.c +34 -54
@@ -683,6 +683,34 @@ static struct trace_probe *find_trace_probe(const char *event,return NULL ; } +/* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ +static int enable_trace_probe (struct trace_probe *tp,int flag) +{ +int ret =0 ; + + tp->flags |= flag; +if (tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE )) { +if (trace_probe_is_return (tp)) + ret =enable_kretprobe (&tp->rp); +else + ret =enable_kprobe (&tp->rp.kp); + } + +return ret; +} + +/* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ +static void disable_trace_probe (struct trace_probe *tp,int flag) +{ + tp->flags &= ~flag; +if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) { +if (trace_probe_is_return (tp)) +disable_kretprobe (&tp->rp); +else +disable_kprobe (&tp->rp.kp); + } +} +/* Unregister a trace_probe and probe_event: call with locking probe_lock */ static void unregister_trace_probe (struct trace_probe *tp) {
@@ -1512,30 +1540,6 @@ partial:return TRACE_TYPE_PARTIAL_LINE ; } -static int probe_event_enable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags |=TP_FLAG_TRACE ; -if (trace_probe_is_return (tp)) -return enable_kretprobe (&tp->rp); -else -return enable_kprobe (&tp->rp.kp); -} - -static void probe_event_disable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags &= ~TP_FLAG_TRACE ; -if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) { -if (trace_probe_is_return (tp)) -disable_kretprobe (&tp->rp); -else -disable_kprobe (&tp->rp.kp); - } -} -#undef DEFINE_FIELD#define DEFINE_FIELD (type, item, name, is_signed) \ do { \
@@ -1714,49 +1718,25 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, head =this_cpu_ptr (call->perf_events); perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head); } - -static int probe_perf_enable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags |=TP_FLAG_PROFILE ; - -if (trace_probe_is_return (tp)) -return enable_kretprobe (&tp->rp); -else -return enable_kprobe (&tp->rp.kp); -} - -static void probe_perf_disable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags &= ~TP_FLAG_PROFILE ; - -if (!(tp->flags &TP_FLAG_TRACE )) { -if (trace_probe_is_return (tp)) -disable_kretprobe (&tp->rp); -else -disable_kprobe (&tp->rp.kp); - } -}#endif /* CONFIG_PERF_EVENTS */ static __kprobes int kprobe_register (struct ftrace_event_call *event,enum trace_reg type) { +struct trace_probe *tp = (struct trace_probe *)event->data; +switch (type) {case TRACE_REG_REGISTER : -return probe_event_enable (event); +return enable_trace_probe (tp,TP_FLAG_TRACE );case TRACE_REG_UNREGISTER : -probe_event_disable (event); +disable_trace_probe (tp,TP_FLAG_TRACE );return 0 ;#ifdef CONFIG_PERF_EVENTS case TRACE_REG_PERF_REGISTER : -return probe_perf_enable (event); +return enable_trace_probe (tp,TP_FLAG_PROFILE );case TRACE_REG_PERF_UNREGISTER : -probe_perf_disable (event); +disable_trace_probe (tp,TP_FLAG_PROFILE );return 0 ;#endif }
Steven Rostedt
maintainerRe: [PATCH -tip 02/13] [CLEANUP]tracing/kprobes: merge trace probe enable/disable functions
Quoted 22 lines · Masami Hiramatsu
Merge redundant enable/disable functions into
enable_trace_probe()anddisable_trace_probe().Signed-off-by Masami Hiramatsu <[email protected]>Cc Steven Rostedt <[email protected]>Cc Frederic Weisbecker <[email protected]>Cc Ingo Molnar <[email protected]>---
kernel/trace/trace_kprobe.c | 88 +++++++++++++++++-------------------------- 1 files changed, 34 insertions(+), 54 deletions(-)kernel/trace/trace_kprobe.c +2
-0@@ -683,6 +683,34 @@ static struct trace_probe *find_trace_probe(const char *event,return NULL ; } +/* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ +static int enable_trace_probe (struct trace_probe *tp,int flag)
kernel/trace/trace_kprobe.c static struct trace_probe *find_trace_probe(const char *event, · line 697
Quoted 10 lines
kernel/trace/trace_kprobe.c +10
-0+{ +int ret =0 ; + + tp->flags |= flag; +if (tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE )) { +if (trace_probe_is_return (tp)) + ret =enable_kretprobe (&tp->rp); +else + ret =enable_kprobe (&tp->rp.kp); + }
Hmm, this seems weird. Should we have any protection here? I mean, is it ok to call the enable_kprobe() twice? Or should we have something like:
{
int old_flags = tp->flags;
int ret = 0;
tp->flags |= flag;
if (!(old_flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE)) &&
flag & (TP_FLAG_TRACE | TP_FLAG_PROFILE)) {
[...]
}
return ret;
}Quoted 5 lines
kernel/trace/trace_kprobe.c +5
-0+ +return ret; +} + +/* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */
kernel/trace/trace_kprobe.c static struct trace_probe *find_trace_probe(const char *event, · line 712
Quoted 10 lines
kernel/trace/trace_kprobe.c +10
-0+static void disable_trace_probe (struct trace_probe *tp,int flag) +{ + tp->flags &= ~flag; +if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) { +if (trace_probe_is_return (tp)) +disable_kretprobe (&tp->rp); +else +disable_kprobe (&tp->rp.kp); + } +}
Same here.
Or do we want to reenable or re disable the probe?
-- Steve
Quoted 91 lines
kernel/trace/trace_kprobe.c +7
-54+/* Unregister a trace_probe and probe_event: call with locking probe_lock */ static void unregister_trace_probe (struct trace_probe *tp) {@@ -1512,30 +1540,6 @@ partial:return TRACE_TYPE_PARTIAL_LINE ; } -static int probe_event_enable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags |=TP_FLAG_TRACE ; -if (trace_probe_is_return (tp)) -return enable_kretprobe (&tp->rp); -else -return enable_kprobe (&tp->rp.kp); -} - -static void probe_event_disable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags &= ~TP_FLAG_TRACE ; -if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) { -if (trace_probe_is_return (tp)) -disable_kretprobe (&tp->rp); -else -disable_kprobe (&tp->rp.kp); - } -} -#undef DEFINE_FIELD#define DEFINE_FIELD (type, item, name, is_signed) \ do { \@@ -1714,49 +1718,25 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, head =this_cpu_ptr (call->perf_events); perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head); } - -static int probe_perf_enable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags |=TP_FLAG_PROFILE ; - -if (trace_probe_is_return (tp)) -return enable_kretprobe (&tp->rp); -else -return enable_kprobe (&tp->rp.kp); -} - -static void probe_perf_disable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags &= ~TP_FLAG_PROFILE ; - -if (!(tp->flags &TP_FLAG_TRACE )) { -if (trace_probe_is_return (tp)) -disable_kretprobe (&tp->rp); -else -disable_kprobe (&tp->rp.kp); - } -}#endif /* CONFIG_PERF_EVENTS */ static __kprobes int kprobe_register (struct ftrace_event_call *event,enum trace_reg type) { +struct trace_probe *tp = (struct trace_probe *)event->data; +switch (type) {case TRACE_REG_REGISTER : -return probe_event_enable (event); +return enable_trace_probe (tp,TP_FLAG_TRACE );case TRACE_REG_UNREGISTER : -probe_event_disable (event); +disable_trace_probe (tp,TP_FLAG_TRACE );return 0 ;#ifdef CONFIG_PERF_EVENTS case TRACE_REG_PERF_REGISTER : -return probe_perf_enable (event); +return enable_trace_probe (tp,TP_FLAG_PROFILE );case TRACE_REG_PERF_UNREGISTER : -probe_perf_disable (event); +disable_trace_probe (tp,TP_FLAG_PROFILE );return 0 ;#endif }
Re: [PATCH -tip 02/13] [CLEANUP]tracing/kprobes: merge trace probe enable/disable functions
Quoted 10 lines · Steven Rostedt
Quoted 9 lines · Masami Hiramatsu
Merge redundant enable/disable functions into
enable_trace_probe()anddisable_trace_probe().Signed-off-by Masami Hiramatsu <[email protected]>Cc Steven Rostedt <[email protected]>Cc Frederic Weisbecker <[email protected]>Cc Ingo Molnar <[email protected]>---
Quoted 8 lines
kernel/trace/trace_kprobe.c static struct trace_probe *find_trace_probe(const char
Quoted 8 lines
kernel/trace/trace_kprobe.c | 88 +++++++++++++++++-------------------------- 1 files changed, 34 insertions(+), 54 deletions(-)kernel/trace/trace_kprobe.c +0
-0@@ -683,6 +683,34 @@ static struct trace_probe *find_trace_probe(const char
*event,
Quoted 19 lines
Quoted 5 lines
kernel/trace/trace_kprobe.c +2
-0return NULL ; } +/* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ +static int enable_trace_probe (struct trace_probe *tp,int flag)kernel/trace/trace_kprobe.c static struct trace_probe *find_trace_probe(const char *event, · line 697
Quoted 10 lines
kernel/trace/trace_kprobe.c +10
-0+{ +int ret =0 ; + + tp->flags |= flag; +if (tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE )) { +if (trace_probe_is_return (tp)) + ret =enable_kretprobe (&tp->rp); +else + ret =enable_kprobe (&tp->rp.kp); + }Hmm, this seems weird. Should we have any protection here? I mean, is it ok to call the
enable_kprobe()twice? Or should we have something like:
Quoted 13 lines
{
int old_flags = tp->flags;
int ret = 0;
tp->flags |= flag;
if (!(old_flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE)) &&
flag & (TP_FLAG_TRACE | TP_FLAG_PROFILE)) {
[...]
}
return ret;
}Ah, no problem, enable_kprobe() enables given kprobe only if it is disabled.
Quoted 11 lines
Quoted 11 lines
kernel/trace/trace_kprobe.c +9
-0+ +return ret; +} + +/* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ +static void disable_trace_probe (struct trace_probe *tp,int flag) +{ + tp->flags &= ~flag; +if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) {
Quoted 8 lines
kernel/trace/trace_kprobe.c static struct trace_probe *find_trace_probe(const char *event, · line 712
Quoted 6 lines
kernel/trace/trace_kprobe.c +6
-0+if (trace_probe_is_return (tp)) +disable_kretprobe (&tp->rp); +else +disable_kprobe (&tp->rp.kp); + } +}Same here.
Same as above.
Quoted 2 lines
Or do we want to reenable or re disable the probe?
Yeah, we do it for enabling/disabling each event.
Thank you,
Quoted 2 lines
-- Steve
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 -tip 02/13] [CLEANUP]tracing/kprobes: merge trace probe enable/disable functions
In reply to Masami HiramatsuQuoted 8 lines · Masami Hiramatsu
Merge redundant enable/disable functions into
enable_trace_probe()anddisable_trace_probe().Signed-off-by Masami Hiramatsu <[email protected]>Cc Steven Rostedt <[email protected]>Cc Frederic Weisbecker <[email protected]>Cc Ingo Molnar <[email protected]>---
This patch failed to compile with:
/home/rostedt/work/autotest/nobackup/linux-test.git/kernel/trace/trace_kprobe.c: In function 'kprobe_trace_self_tests_init':/home/rostedt/work/autotest/nobackup/linux-test.git/kernel/trace/trace_kprobe.c:1888:4: error: implicit declaration of function 'probe_event_enable'
-- Steve
Re: [PATCH -tip 02/13] [CLEANUP]tracing/kprobes: merge trace probe enable/disable functions
Quoted 10 lines · Steven Rostedt
Quoted 8 lines · Masami Hiramatsu
Merge redundant enable/disable functions into
enable_trace_probe()anddisable_trace_probe().Signed-off-by Masami Hiramatsu <[email protected]>Cc Steven Rostedt <[email protected]>Cc Frederic Weisbecker <[email protected]>Cc Ingo Molnar <[email protected]>---
Quoted 5 lines
This patch failed to compile with:
/home/rostedt/work/autotest/nobackup/linux-test.git/kernel/trace/trace_kprobe.c: In function 'kprobe_trace_self_tests_init':/home/rostedt/work/autotest/nobackup/linux-test.git/kernel/trace/trace_kprobe.c:1888:4: error: implicit declaration of function 'probe_event_enable'
Oops, it was my fault... I'll update it soon.
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
PATCH v2 1/1 tracing/kprobes: merge trace probe enable/disable functions
In reply to Steven RostedtMerge redundant enable/disable functions into enable_trace_probe() and disable_trace_probe().
Changes from v1:
- replace probe_event_enable() with enable_trace_probe() in self-test code too.
---
kernel/trace/trace_kprobe.c | 92 +++++++++++++++++-------------------------- 1 files changed, 36 insertions(+), 56 deletions(-)
kernel/trace/trace_kprobe.c +36 -56
@@ -683,6 +683,34 @@ static struct trace_probe *find_trace_probe(const char *event,return NULL ; } +/* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ +static int enable_trace_probe (struct trace_probe *tp,int flag) +{ +int ret =0 ; + + tp->flags |= flag; +if (tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE )) { +if (trace_probe_is_return (tp)) + ret =enable_kretprobe (&tp->rp); +else + ret =enable_kprobe (&tp->rp.kp); + } + +return ret; +} + +/* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ +static void disable_trace_probe (struct trace_probe *tp,int flag) +{ + tp->flags &= ~flag; +if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) { +if (trace_probe_is_return (tp)) +disable_kretprobe (&tp->rp); +else +disable_kprobe (&tp->rp.kp); + } +} +/* Unregister a trace_probe and probe_event: call with locking probe_lock */ static void unregister_trace_probe (struct trace_probe *tp) {
@@ -1514,30 +1542,6 @@ partial:return TRACE_TYPE_PARTIAL_LINE ; } -static int probe_event_enable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags |=TP_FLAG_TRACE ; -if (trace_probe_is_return (tp)) -return enable_kretprobe (&tp->rp); -else -return enable_kprobe (&tp->rp.kp); -} - -static void probe_event_disable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags &= ~TP_FLAG_TRACE ; -if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) { -if (trace_probe_is_return (tp)) -disable_kretprobe (&tp->rp); -else -disable_kprobe (&tp->rp.kp); - } -} -#undef DEFINE_FIELD#define DEFINE_FIELD (type, item, name, is_signed) \ do { \
@@ -1716,49 +1720,25 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, head =this_cpu_ptr (call->perf_events); perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head); } - -static int probe_perf_enable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags |=TP_FLAG_PROFILE ; - -if (trace_probe_is_return (tp)) -return enable_kretprobe (&tp->rp); -else -return enable_kprobe (&tp->rp.kp); -} - -static void probe_perf_disable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags &= ~TP_FLAG_PROFILE ; - -if (!(tp->flags &TP_FLAG_TRACE )) { -if (trace_probe_is_return (tp)) -disable_kretprobe (&tp->rp); -else -disable_kprobe (&tp->rp.kp); - } -}#endif /* CONFIG_PERF_EVENTS */ static __kprobes int kprobe_register (struct ftrace_event_call *event,enum trace_reg type) { +struct trace_probe *tp = (struct trace_probe *)event->data; +switch (type) {case TRACE_REG_REGISTER : -return probe_event_enable (event); +return enable_trace_probe (tp,TP_FLAG_TRACE );case TRACE_REG_UNREGISTER : -probe_event_disable (event); +disable_trace_probe (tp,TP_FLAG_TRACE );return 0 ;#ifdef CONFIG_PERF_EVENTS case TRACE_REG_PERF_REGISTER : -return probe_perf_enable (event); +return enable_trace_probe (tp,TP_FLAG_PROFILE );case TRACE_REG_PERF_UNREGISTER : -probe_perf_disable (event); +disable_trace_probe (tp,TP_FLAG_PROFILE );return 0 ;#endif }
@@ -1905,7 +1885,7 @@ static __init int kprobe_trace_self_tests_init(void)pr_warning ("error on getting new probe.\n" ); warn++; }else -probe_event_enable (&tp->call); +enable_trace_probe (tp,TP_FLAG_TRACE ); } ret = command_trace_probe("r:testprobe2 kprobe_trace_selftest_target "
@@ -1920,7 +1900,7 @@ static __init int kprobe_trace_self_tests_init(void)pr_warning ("error on getting new probe.\n" ); warn++; }else -probe_event_enable (&tp->call); +enable_trace_probe (tp,TP_FLAG_TRACE ); }if (warn)
Steven Rostedt
maintainerRe: [PATCH -tip v2] [CLEANUP]tracing/kprobes: merge trace probe enable/disable functions
Quoted 6 lines · Masami Hiramatsu
Merge redundant enable/disable functions into
enable_trace_probe()anddisable_trace_probe().Changes from v1:
- replaceprobe_event_enable()withenable_trace_probe()in self-test code too.
Ah, I already fixed it and ran it through all my tests. I'll send it out in a minute. I'll make sure I fixed it the same way first.
Thanks!
-- Steve
Quoted 155 lines
Signed-off-by Masami Hiramatsu <[email protected]>Cc Steven Rostedt <[email protected]>Cc Frederic Weisbecker <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>---
kernel/trace/trace_kprobe.c | 92 +++++++++++++++++-------------------------- 1 files changed, 36 insertions(+), 56 deletions(-)kernel/trace/trace_kprobe.c +36
-56@@ -683,6 +683,34 @@ static struct trace_probe *find_trace_probe(const char *event,return NULL ; } +/* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ +static int enable_trace_probe (struct trace_probe *tp,int flag) +{ +int ret =0 ; + + tp->flags |= flag; +if (tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE )) { +if (trace_probe_is_return (tp)) + ret =enable_kretprobe (&tp->rp); +else + ret =enable_kprobe (&tp->rp.kp); + } + +return ret; +} + +/* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ +static void disable_trace_probe (struct trace_probe *tp,int flag) +{ + tp->flags &= ~flag; +if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) { +if (trace_probe_is_return (tp)) +disable_kretprobe (&tp->rp); +else +disable_kprobe (&tp->rp.kp); + } +} +/* Unregister a trace_probe and probe_event: call with locking probe_lock */ static void unregister_trace_probe (struct trace_probe *tp) {@@ -1514,30 +1542,6 @@ partial:return TRACE_TYPE_PARTIAL_LINE ; } -static int probe_event_enable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags |=TP_FLAG_TRACE ; -if (trace_probe_is_return (tp)) -return enable_kretprobe (&tp->rp); -else -return enable_kprobe (&tp->rp.kp); -} - -static void probe_event_disable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags &= ~TP_FLAG_TRACE ; -if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) { -if (trace_probe_is_return (tp)) -disable_kretprobe (&tp->rp); -else -disable_kprobe (&tp->rp.kp); - } -} -#undef DEFINE_FIELD#define DEFINE_FIELD (type, item, name, is_signed) \ do { \@@ -1716,49 +1720,25 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, head =this_cpu_ptr (call->perf_events); perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head); } - -static int probe_perf_enable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags |=TP_FLAG_PROFILE ; - -if (trace_probe_is_return (tp)) -return enable_kretprobe (&tp->rp); -else -return enable_kprobe (&tp->rp.kp); -} - -static void probe_perf_disable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags &= ~TP_FLAG_PROFILE ; - -if (!(tp->flags &TP_FLAG_TRACE )) { -if (trace_probe_is_return (tp)) -disable_kretprobe (&tp->rp); -else -disable_kprobe (&tp->rp.kp); - } -}#endif /* CONFIG_PERF_EVENTS */ static __kprobes int kprobe_register (struct ftrace_event_call *event,enum trace_reg type) { +struct trace_probe *tp = (struct trace_probe *)event->data; +switch (type) {case TRACE_REG_REGISTER : -return probe_event_enable (event); +return enable_trace_probe (tp,TP_FLAG_TRACE );case TRACE_REG_UNREGISTER : -probe_event_disable (event); +disable_trace_probe (tp,TP_FLAG_TRACE );return 0 ;#ifdef CONFIG_PERF_EVENTS case TRACE_REG_PERF_REGISTER : -return probe_perf_enable (event); +return enable_trace_probe (tp,TP_FLAG_PROFILE );case TRACE_REG_PERF_UNREGISTER : -probe_perf_disable (event); +disable_trace_probe (tp,TP_FLAG_PROFILE );return 0 ;#endif }@@ -1905,7 +1885,7 @@ static __init int kprobe_trace_self_tests_init(void)pr_warning ("error on getting new probe.\n" ); warn++; }else -probe_event_enable (&tp->call); +enable_trace_probe (tp,TP_FLAG_TRACE ); } ret = command_trace_probe("r:testprobe2 kprobe_trace_selftest_target "@@ -1920,7 +1900,7 @@ static __init int kprobe_trace_self_tests_init(void)pr_warning ("error on getting new probe.\n" ); warn++; }else -probe_event_enable (&tp->call); +enable_trace_probe (tp,TP_FLAG_TRACE ); }if (warn)
[tip:perf/core] tracing/kprobes: Merge trace probe enable/disable functions
In reply to Masami HiramatsuCommit-ID: 1538f888f1e793de04e0f90372352ac1b05833cf Gitweb: http://git.kernel.org/tip/1538f888f1e793de04e0f90372352ac1b05833cf Author: Masami Hiramatsu <[email protected]> AuthorDate: Mon, 27 Jun 2011 16:26:44 +0900 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 15 Jul 2011 15:10:58 -0400
tracing/kprobes: Merge trace probe enable/disable functions
Merge redundant enable/disable functions into enable_trace_probe() and disable_trace_probe().
[ converted kprobe selftest to use enable_trace_probe ]
--- kernel/trace/trace_kprobe.c | 92 +++++++++++++++++-------------------------- 1 files changed, 36 insertions(+), 56 deletions(-)
kernel/trace/trace_kprobe.c +36 -56
@@ -683,6 +683,34 @@ static struct trace_probe *find_trace_probe(const char *event,return NULL ; } +/* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ +static int enable_trace_probe (struct trace_probe *tp,int flag) +{ +int ret =0 ; + + tp->flags |= flag; +if (tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE )) { +if (trace_probe_is_return (tp)) + ret =enable_kretprobe (&tp->rp); +else + ret =enable_kprobe (&tp->rp.kp); + } + +return ret; +} + +/* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ +static void disable_trace_probe (struct trace_probe *tp,int flag) +{ + tp->flags &= ~flag; +if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) { +if (trace_probe_is_return (tp)) +disable_kretprobe (&tp->rp); +else +disable_kprobe (&tp->rp.kp); + } +} +/* Unregister a trace_probe and probe_event: call with locking probe_lock */ static void unregister_trace_probe (struct trace_probe *tp) {
@@ -1514,30 +1542,6 @@ partial:return TRACE_TYPE_PARTIAL_LINE ; } -static int probe_event_enable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags |=TP_FLAG_TRACE ; -if (trace_probe_is_return (tp)) -return enable_kretprobe (&tp->rp); -else -return enable_kprobe (&tp->rp.kp); -} - -static void probe_event_disable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags &= ~TP_FLAG_TRACE ; -if (!(tp->flags & (TP_FLAG_TRACE |TP_FLAG_PROFILE ))) { -if (trace_probe_is_return (tp)) -disable_kretprobe (&tp->rp); -else -disable_kprobe (&tp->rp.kp); - } -} -#undef DEFINE_FIELD#define DEFINE_FIELD (type, item, name, is_signed) \ do { \
@@ -1716,49 +1720,25 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, head =this_cpu_ptr (call->perf_events); perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head); } - -static int probe_perf_enable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags |=TP_FLAG_PROFILE ; - -if (trace_probe_is_return (tp)) -return enable_kretprobe (&tp->rp); -else -return enable_kprobe (&tp->rp.kp); -} - -static void probe_perf_disable (struct ftrace_event_call *call) -{ -struct trace_probe *tp = (struct trace_probe *)call->data; - - tp->flags &= ~TP_FLAG_PROFILE ; - -if (!(tp->flags &TP_FLAG_TRACE )) { -if (trace_probe_is_return (tp)) -disable_kretprobe (&tp->rp); -else -disable_kprobe (&tp->rp.kp); - } -}#endif /* CONFIG_PERF_EVENTS */ static __kprobes int kprobe_register (struct ftrace_event_call *event,enum trace_reg type) { +struct trace_probe *tp = (struct trace_probe *)event->data; +switch (type) {case TRACE_REG_REGISTER : -return probe_event_enable (event); +return enable_trace_probe (tp,TP_FLAG_TRACE );case TRACE_REG_UNREGISTER : -probe_event_disable (event); +disable_trace_probe (tp,TP_FLAG_TRACE );return 0 ;#ifdef CONFIG_PERF_EVENTS case TRACE_REG_PERF_REGISTER : -return probe_perf_enable (event); +return enable_trace_probe (tp,TP_FLAG_PROFILE );case TRACE_REG_PERF_UNREGISTER : -probe_perf_disable (event); +disable_trace_probe (tp,TP_FLAG_PROFILE );return 0 ;#endif }
@@ -1905,7 +1885,7 @@ static __init int kprobe_trace_self_tests_init(void)pr_warning ("error on getting new probe.\n" ); warn++; }else -probe_event_enable (&tp->call); +enable_trace_probe (tp,TP_FLAG_TRACE ); } ret = command_trace_probe("r:testprobe2 kprobe_trace_selftest_target "
@@ -1920,7 +1900,7 @@ static __init int kprobe_trace_self_tests_init(void)pr_warning ("error on getting new probe.\n" ); warn++; }else -probe_event_enable (&tp->call); +enable_trace_probe (tp,TP_FLAG_TRACE ); }if (warn)
PATCH 3/13 kprobes: Return -ENOENT if probe point doesn't exist
In reply to Masami HiramatsuReturn -ENOENT if probe point doesn't exist, but still returns -EINVAL if both of kprobe->addr and kprobe->symbol_name are specified or both are not specified.
---
kernel/kprobes.c | 33 +++++++++++++++++++++++---------- 1 files changed, 23 insertions(+), 10 deletions(-)
kernel/kprobes.c +23 -10
@@ -1255,19 +1255,29 @@ static int __kprobes in_kprobes_functions(unsigned long addr)/* * If we have a symbol_name argument, look it up and add the offset field * to it. This way, we can specify a relative address to a symbol. +* This returns encoded errors if it fails to look up symbol or invalid +* combination of parameters. */ static kprobe_opcode_t __kprobes *kprobe_addr (struct kprobe *p) {kprobe_opcode_t *addr = p->addr; + +if ((p->symbol_name && p->addr) || + (!p->symbol_name && !p->addr)) + goto invalid; +if (p->symbol_name) { -if (addr) -return NULL ;kprobe_lookup_name (p->symbol_name, addr); +if (!addr) +return ERR_PTR (-ENOENT ); } -if (!addr) -return NULL ; -return (kprobe_opcode_t *)(((char *)addr) + p->offset); + addr = (kprobe_opcode_t *)(((char *)addr) + p->offset); +if (addr) +return addr; + +invalid: +return ERR_PTR (-EINVAL ); }/* Check passed kprobe is valid and return kprobe in kprobe_table. */
@@ -1311,8 +1321,8 @@ int __kprobes register_kprobe(struct kprobe *p)kprobe_opcode_t *addr; addr =kprobe_addr (p); -if (!addr) -return -EINVAL ; +if (IS_ERR (addr)) +return PTR_ERR (addr); p->addr = addr; ret =check_kprobe_rereg (p);
@@ -1335,6 +1345,8 @@ int __kprobes register_kprobe(struct kprobe *p)*/ probed_mod =__module_text_address ((unsigned long ) p->addr);if (probed_mod) { +/* Return -ENOENT if fail. */ + ret = -ENOENT ;/* * We must hold a refcount of the probed module while updating * its code to prohibit unexpected unloading.
@@ -1351,6 +1363,7 @@ int __kprobes register_kprobe(struct kprobe *p)module_put (probed_mod); goto fail_with_jump_label; } +/* ret will be updated by following code */ }preempt_enable ();jump_label_unlock ();
@@ -1399,7 +1412,7 @@ out: fail_with_jump_label:preempt_enable ();jump_label_unlock (); -return -EINVAL ; +return ret; }EXPORT_SYMBOL_GPL (register_kprobe);
@@ -1686,8 +1699,8 @@ int __kprobes register_kretprobe(struct kretprobe *rp)if (kretprobe_blacklist_size) { addr =kprobe_addr (&rp->kp); -if (!addr) -return -EINVAL ; +if (IS_ERR (addr)) +return PTR_ERR (addr);for (i =0 ; kretprobe_blacklist[i].name !=NULL ; i++) {if (kretprobe_blacklist[i].addr == addr)
Re: [PATCH -tip 03/13] kprobes: Return -ENOENT if probe point doesn't exist
Quoted 6 lines · Masami Hiramatsu
Return
-ENOENTif probe point doesn't exist, but still returns-EINVALif both ofkprobe->addrandkprobe->symbol_nameare specified or both are not specified.Signed-off-by Masami Hiramatsu <[email protected]>Cc Ananth N Mavinakayanahalli <[email protected]>
[tip:perf/core] kprobes: Return -ENOENT if probe point doesn't exist
In reply to Masami HiramatsuCommit-ID: bc81d48d13d8839fae6833c95794c403b2133f36 Gitweb: http://git.kernel.org/tip/bc81d48d13d8839fae6833c95794c403b2133f36 Author: Masami Hiramatsu <[email protected]> AuthorDate: Mon, 27 Jun 2011 16:26:50 +0900 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 15 Jul 2011 15:11:47 -0400
kprobes: Return -ENOENT if probe point doesn't exist
Return -ENOENT if probe point doesn't exist, but still returns -EINVAL if both of kprobe->addr and kprobe->symbol_name are specified or both are not specified.
--- kernel/kprobes.c | 33 +++++++++++++++++++++++---------- 1 files changed, 23 insertions(+), 10 deletions(-)
kernel/kprobes.c +23 -10
@@ -1255,19 +1255,29 @@ static int __kprobes in_kprobes_functions(unsigned long addr)/* * If we have a symbol_name argument, look it up and add the offset field * to it. This way, we can specify a relative address to a symbol. +* This returns encoded errors if it fails to look up symbol or invalid +* combination of parameters. */ static kprobe_opcode_t __kprobes *kprobe_addr (struct kprobe *p) {kprobe_opcode_t *addr = p->addr; + +if ((p->symbol_name && p->addr) || + (!p->symbol_name && !p->addr)) + goto invalid; +if (p->symbol_name) { -if (addr) -return NULL ;kprobe_lookup_name (p->symbol_name, addr); +if (!addr) +return ERR_PTR (-ENOENT ); } -if (!addr) -return NULL ; -return (kprobe_opcode_t *)(((char *)addr) + p->offset); + addr = (kprobe_opcode_t *)(((char *)addr) + p->offset); +if (addr) +return addr; + +invalid: +return ERR_PTR (-EINVAL ); }/* Check passed kprobe is valid and return kprobe in kprobe_table. */
@@ -1311,8 +1321,8 @@ int __kprobes register_kprobe(struct kprobe *p)kprobe_opcode_t *addr; addr =kprobe_addr (p); -if (!addr) -return -EINVAL ; +if (IS_ERR (addr)) +return PTR_ERR (addr); p->addr = addr; ret =check_kprobe_rereg (p);
@@ -1335,6 +1345,8 @@ int __kprobes register_kprobe(struct kprobe *p)*/ probed_mod =__module_text_address ((unsigned long ) p->addr);if (probed_mod) { +/* Return -ENOENT if fail. */ + ret = -ENOENT ;/* * We must hold a refcount of the probed module while updating * its code to prohibit unexpected unloading.
@@ -1351,6 +1363,7 @@ int __kprobes register_kprobe(struct kprobe *p)module_put (probed_mod); goto fail_with_jump_label; } +/* ret will be updated by following code */ }preempt_enable ();jump_label_unlock ();
@@ -1399,7 +1412,7 @@ out: fail_with_jump_label:preempt_enable ();jump_label_unlock (); -return -EINVAL ; +return ret; }EXPORT_SYMBOL_GPL (register_kprobe);
@@ -1686,8 +1699,8 @@ int __kprobes register_kretprobe(struct kretprobe *rp)if (kretprobe_blacklist_size) { addr =kprobe_addr (&rp->kp); -if (!addr) -return -EINVAL ; +if (IS_ERR (addr)) +return PTR_ERR (addr);for (i =0 ; kretprobe_blacklist[i].name !=NULL ; i++) {if (kretprobe_blacklist[i].addr == addr)
PATCH 4/13 tracing/kprobes: Support module init function probing
In reply to Masami HiramatsuTo support probing module init functions, kprobe-tracer allows user to define a probe on non-existed function when it is given with a module name. This also enables user to set a probe on a function on a specific module, even if a same name (but different) function is locally defined in another module.
The module name must be in the front of function name and separated by a ':'. e.g. btrfs:btrfs_init_sysfs
---
Documentation/trace/kprobetrace.txt | 9 +- kernel/trace/trace_kprobe.c | 164 +++++++++++++++++++++++++++++------ 2 files changed, 143 insertions(+), 30 deletions(-)
Documentation/trace/kprobetrace.txt +5 -4
@@ -22,14 +22,15 @@ current_tracer. Instead of that, add probe points via Synopsis of kprobe_events ------------------------- - p[:[GRP/]EVENT] SYMBOL[+offs]|MEMADDR [FETCHARGS] : Set a probe - r[:[GRP/]EVENT] SYMBOL[+0] [FETCHARGS] : Set a return probe + p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] : Set a probe + r[:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS] : Set a return probe -:[GRP/]EVENT : Clear a probe GRP : Group name. If omitted, use "kprobes" for it. EVENT : Event name. If omitted, the event name is generated - based on SYMBOL+offs or MEMADDR. - SYMBOL[+offs] : Symbol+offset where the probe is inserted. + based on SYM+offs or MEMADDR. + MOD : Module name which has given SYM. + SYM[+offs] : Symbol+offset where the probe is inserted. MEMADDR : Address where the probe is inserted. FETCHARGS : Arguments. Each probe can have up to 128 args.
kernel/trace/trace_kprobe.c +138 -26
239 lines not on this page · raw message
[tip:perf/core] tracing/kprobes: Support module init function probing
Commit-ID: 614243181050436785f5a621749a7da2336a7916 Gitweb: http://git.kernel.org/tip/614243181050436785f5a621749a7da2336a7916 Author: Masami Hiramatsu <[email protected]> AuthorDate: Mon, 27 Jun 2011 16:26:56 +0900 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 15 Jul 2011 15:17:14 -0400
tracing/kprobes: Support module init function probing
To support probing module init functions, kprobe-tracer allows user to define a probe on non-existed function when it is given with a module name. This also enables user to set a probe on a function on a specific module, even if a same name (but different) function is locally defined in another module.
The module name must be in the front of function name and separated by a ':'. e.g. btrfs:btrfs_init_sysfs
--- Documentation/trace/kprobetrace.txt | 9 +- kernel/trace/trace_kprobe.c | 164 +++++++++++++++++++++++++++++------ 2 files changed, 143 insertions(+), 30 deletions(-)
Documentation/trace/kprobetrace.txt +5 -4
@@ -22,14 +22,15 @@ current_tracer. Instead of that, add probe points via Synopsis of kprobe_events ------------------------- - p[:[GRP/]EVENT] SYMBOL[+offs]|MEMADDR [FETCHARGS] : Set a probe - r[:[GRP/]EVENT] SYMBOL[+0] [FETCHARGS] : Set a return probe + p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] : Set a probe + r[:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS] : Set a return probe -:[GRP/]EVENT : Clear a probe GRP : Group name. If omitted, use "kprobes" for it. EVENT : Event name. If omitted, the event name is generated - based on SYMBOL+offs or MEMADDR. - SYMBOL[+offs] : Symbol+offset where the probe is inserted. + based on SYM+offs or MEMADDR. + MOD : Module name which has given SYM. + SYM[+offs] : Symbol+offset where the probe is inserted. MEMADDR : Address where the probe is inserted. FETCHARGS : Arguments. Each probe can have up to 128 args.
kernel/trace/trace_kprobe.c +138 -26
239 lines not on this page · raw message
PATCH 5/13 tracing/kprobe: Update symbol reference when loading module
In reply to Masami HiramatsuSince the address of a module-local variable can only be solved after the target module is loaded, the symbol fetch-argument should be updated when loading target module.
---
kernel/trace/trace_kprobe.c | 37 ++++++++++++++++++++++++++++++++++++- 1 files changed, 36 insertions(+), 1 deletions(-)
kernel/trace/trace_kprobe.c +36 -1
@@ -343,6 +343,14 @@ DEFINE_BASIC_FETCH_FUNCS(deref) DEFINE_FETCH_deref(string) DEFINE_FETCH_deref(string_size) +static __kprobes void update_deref_fetch_param(struct deref_fetch_param *data) +{ + if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) + update_deref_fetch_param(data->orig.data); + else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) + update_symbol_cache(data->orig.data); +} + static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) { if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
@@ -377,6 +385,19 @@ DEFINE_BASIC_FETCH_FUNCS(bitfield)#define fetch_bitfield_string_size NULLstatic __kprobes void +update_bitfield_fetch_param (struct bitfield_fetch_param *data) +{ +/* +* Don't check the bitfield itself, because this must be the +* last fetch function. +*/ +if (CHECK_FETCH_FUNCS (deref, data->orig.fn)) +update_deref_fetch_param (data->orig.data); +else if (CHECK_FETCH_FUNCS (symbol, data->orig.fn)) +update_symbol_cache (data->orig.data); +} + +static __kprobes void free_bitfield_fetch_param (struct bitfield_fetch_param *data) {/*
@@ -389,6 +410,7 @@ free_bitfield_fetch_param(struct bitfield_fetch_param *data)free_symbol_cache (data->orig.data);kfree (data); } +/* Default (unsigned long) fetch type */ #define __DEFAULT_FETCH_TYPE (t) u##t#define _DEFAULT_FETCH_TYPE (t) __DEFAULT_FETCH_TYPE(t)
@@ -680,6 +702,16 @@ error:return ERR_PTR (ret); } +static void update_probe_arg (struct probe_arg *arg) +{ +if (CHECK_FETCH_FUNCS (bitfield, arg->fetch.fn)) +update_bitfield_fetch_param (arg->fetch.data); +else if (CHECK_FETCH_FUNCS (deref, arg->fetch.fn)) +update_deref_fetch_param (arg->fetch.data); +else if (CHECK_FETCH_FUNCS (symbol, arg->fetch.fn)) +update_symbol_cache (arg->fetch.data); +} +static void free_probe_arg (struct probe_arg *arg) {if (CHECK_FETCH_FUNCS (bitfield, arg->fetch.fn))
@@ -749,11 +781,14 @@ static void disable_trace_probe(struct trace_probe *tp, int flag)/* Internal register function - just handle k*probes and flags */ static int __register_trace_probe (struct trace_probe *tp) { -int ret; +int i, ret;if (trace_probe_is_registered (tp))return -EINVAL ; +for (i =0 ; i < tp->nr_args; i++) +update_probe_arg (&tp->args[i]); +/* Set/clear disabled flag according to tp->flag */ if (trace_probe_is_enabled (tp)) tp->rp.kp.flags &= ~KPROBE_FLAG_DISABLED ;
[tip:perf/core] tracing/kprobe: Update symbol reference when loading module
Commit-ID: 7f6878a3d707b947603e09d95df0c3a98987e3a4 Gitweb: http://git.kernel.org/tip/7f6878a3d707b947603e09d95df0c3a98987e3a4 Author: Masami Hiramatsu <[email protected]> AuthorDate: Mon, 27 Jun 2011 16:27:03 +0900 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 15 Jul 2011 15:45:32 -0400
tracing/kprobe: Update symbol reference when loading module
Since the address of a module-local variable can only be solved after the target module is loaded, the symbol fetch-argument should be updated when loading target module.
--- kernel/trace/trace_kprobe.c | 37 ++++++++++++++++++++++++++++++++++++- 1 files changed, 36 insertions(+), 1 deletions(-)
kernel/trace/trace_kprobe.c +36 -1
@@ -343,6 +343,14 @@ DEFINE_BASIC_FETCH_FUNCS(deref) DEFINE_FETCH_deref(string) DEFINE_FETCH_deref(string_size) +static __kprobes void update_deref_fetch_param(struct deref_fetch_param *data) +{ + if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) + update_deref_fetch_param(data->orig.data); + else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) + update_symbol_cache(data->orig.data); +} + static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) { if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
@@ -377,6 +385,19 @@ DEFINE_BASIC_FETCH_FUNCS(bitfield)#define fetch_bitfield_string_size NULLstatic __kprobes void +update_bitfield_fetch_param (struct bitfield_fetch_param *data) +{ +/* +* Don't check the bitfield itself, because this must be the +* last fetch function. +*/ +if (CHECK_FETCH_FUNCS (deref, data->orig.fn)) +update_deref_fetch_param (data->orig.data); +else if (CHECK_FETCH_FUNCS (symbol, data->orig.fn)) +update_symbol_cache (data->orig.data); +} + +static __kprobes void free_bitfield_fetch_param (struct bitfield_fetch_param *data) {/*
@@ -389,6 +410,7 @@ free_bitfield_fetch_param(struct bitfield_fetch_param *data)free_symbol_cache (data->orig.data);kfree (data); } +/* Default (unsigned long) fetch type */ #define __DEFAULT_FETCH_TYPE (t) u##t#define _DEFAULT_FETCH_TYPE (t) __DEFAULT_FETCH_TYPE(t)
@@ -680,6 +702,16 @@ error:return ERR_PTR (ret); } +static void update_probe_arg (struct probe_arg *arg) +{ +if (CHECK_FETCH_FUNCS (bitfield, arg->fetch.fn)) +update_bitfield_fetch_param (arg->fetch.data); +else if (CHECK_FETCH_FUNCS (deref, arg->fetch.fn)) +update_deref_fetch_param (arg->fetch.data); +else if (CHECK_FETCH_FUNCS (symbol, arg->fetch.fn)) +update_symbol_cache (arg->fetch.data); +} +static void free_probe_arg (struct probe_arg *arg) {if (CHECK_FETCH_FUNCS (bitfield, arg->fetch.fn))
@@ -749,11 +781,14 @@ static void disable_trace_probe(struct trace_probe *tp, int flag)/* Internal register function - just handle k*probes and flags */ static int __register_trace_probe (struct trace_probe *tp) { -int ret; +int i, ret;if (trace_probe_is_registered (tp))return -EINVAL ; +for (i =0 ; i < tp->nr_args; i++) +update_probe_arg (&tp->args[i]); +/* Set/clear disabled flag according to tp->flag */ if (trace_probe_is_enabled (tp)) tp->rp.kp.flags &= ~KPROBE_FLAG_DISABLED ;
PATCH RESEND 6/13 perf probe: Rename DIE_FIND_CB_FOUND to DIE_FIND_CB_END
In reply to Masami HiramatsuSince die_find/walk* callbacks use DIE_FIND_CB_FOUND for both of failed and found cases, it should be "END" instead "FOUND" for avoiding confusion.
---
tools/perf/util/probe-finder.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
tools/perf/util/probe-finder.c +6 -6
@@ -435,7 +435,7 @@ static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)/* Return values for die_find callbacks */ enum { -DIE_FIND_CB_FOUND =0 ,/* End of Search */ +DIE_FIND_CB_END =0 ,/* End of Search */ DIE_FIND_CB_CHILD =1 ,/* Search only children */ DIE_FIND_CB_SIBLING =2 ,/* Search only siblings */ DIE_FIND_CB_CONTINUE =3 ,/* Search children and siblings */
@@ -455,7 +455,7 @@ static Dwarf_Die *die_find_child(Dwarf_Die *rt_die, do { ret = callback(die_mem, data); - if (ret == DIE_FIND_CB_FOUND) + if (ret == DIE_FIND_CB_END) return die_mem; if ((ret & DIE_FIND_CB_CHILD) &&
@@ -507,7 +507,7 @@ static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)if (dwarf_tag (die_mem) == DW_TAG_inlined_subroutine &&dwarf_haspc (die_mem, *addr)) -return DIE_FIND_CB_FOUND ; +return DIE_FIND_CB_END ;return DIE_FIND_CB_CONTINUE ; }
@@ -555,7 +555,7 @@ static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data) lw->retval = lw->handler (lw->fname, lineno, addr, lw->data);if (lw->retval !=0 ) -return DIE_FIND_CB_FOUND ; +return DIE_FIND_CB_END ; } }return DIE_FIND_CB_SIBLING ;
@@ -691,7 +691,7 @@ static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)if ((tag == DW_TAG_formal_parameter || tag == DW_TAG_variable) &&die_compare_name (die_mem, fvp->name)) -return DIE_FIND_CB_FOUND ; +return DIE_FIND_CB_END ;if (dwarf_haspc (die_mem, fvp->addr))return DIE_FIND_CB_CONTINUE ;
@@ -715,7 +715,7 @@ static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)if ((dwarf_tag (die_mem) == DW_TAG_member) &&die_compare_name (die_mem, name)) -return DIE_FIND_CB_FOUND ; +return DIE_FIND_CB_END ;return DIE_FIND_CB_SIBLING ; }
[tip:perf/core] perf probe: Rename DIE_FIND_CB_FOUND to DIE_FIND_CB_END
Commit-ID: baad2d3e69ba154dae340904a47ae12414f1894f Gitweb: http://git.kernel.org/tip/baad2d3e69ba154dae340904a47ae12414f1894f Author: Masami Hiramatsu <[email protected]> AuthorDate: Mon, 27 Jun 2011 16:27:09 +0900 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 15 Jul 2011 15:55:57 -0400
perf probe: Rename DIE_FIND_CB_FOUND to DIE_FIND_CB_END
Since die_find/walk* callbacks use DIE_FIND_CB_FOUND for both of failed and found cases, it should be "END" instead "FOUND" for avoiding confusion.
--- tools/perf/util/probe-finder.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
tools/perf/util/probe-finder.c +6 -6
@@ -435,7 +435,7 @@ static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)/* Return values for die_find callbacks */ enum { -DIE_FIND_CB_FOUND =0 ,/* End of Search */ +DIE_FIND_CB_END =0 ,/* End of Search */ DIE_FIND_CB_CHILD =1 ,/* Search only children */ DIE_FIND_CB_SIBLING =2 ,/* Search only siblings */ DIE_FIND_CB_CONTINUE =3 ,/* Search children and siblings */
@@ -455,7 +455,7 @@ static Dwarf_Die *die_find_child(Dwarf_Die *rt_die, do { ret = callback(die_mem, data); - if (ret == DIE_FIND_CB_FOUND) + if (ret == DIE_FIND_CB_END) return die_mem; if ((ret & DIE_FIND_CB_CHILD) &&
@@ -507,7 +507,7 @@ static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)if (dwarf_tag (die_mem) == DW_TAG_inlined_subroutine &&dwarf_haspc (die_mem, *addr)) -return DIE_FIND_CB_FOUND ; +return DIE_FIND_CB_END ;return DIE_FIND_CB_CONTINUE ; }
@@ -555,7 +555,7 @@ static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data) lw->retval = lw->handler (lw->fname, lineno, addr, lw->data);if (lw->retval !=0 ) -return DIE_FIND_CB_FOUND ; +return DIE_FIND_CB_END ; } }return DIE_FIND_CB_SIBLING ;
@@ -691,7 +691,7 @@ static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)if ((tag == DW_TAG_formal_parameter || tag == DW_TAG_variable) &&die_compare_name (die_mem, fvp->name)) -return DIE_FIND_CB_FOUND ; +return DIE_FIND_CB_END ;if (dwarf_haspc (die_mem, fvp->addr))return DIE_FIND_CB_CONTINUE ;
@@ -715,7 +715,7 @@ static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)if ((dwarf_tag (die_mem) == DW_TAG_member) &&die_compare_name (die_mem, name)) -return DIE_FIND_CB_FOUND ; +return DIE_FIND_CB_END ;return DIE_FIND_CB_SIBLING ; }
PATCH RESEND 7/13 perf probe: Move strtailcmp to string.c
In reply to Masami HiramatsuSince strtailcmp() is enough generic, it should be defined in string.c.
---
tools/perf/util/probe-finder.c | 15 --------------- tools/perf/util/string.c | 19 +++++++++++++++++++ tools/perf/util/util.h | 1 + 3 files changed, 20 insertions(+), 15 deletions(-)
tools/perf/util/probe-finder.c +0 -15
@@ -43,21 +43,6 @@/* Kprobe tracer basic type is up to u64 */ #define MAX_BASIC_TYPE_BITS 64 -/* -* Compare the tail of two strings. -* Return 0 if whole of either string is same as another's tail part. -*/ -static int strtailcmp (const char *s1,const char *s2) -{ -int i1 =strlen (s1); -int i2 =strlen (s2); -while (--i1 >=0 && --i2 >=0 ) { -if (s1[i1] != s2[i2]) -return s1[i1] - s2[i2]; - } -return 0 ; -} -/* Line number list operations */ /* Add a line to line number list */
tools/perf/util/string.c +19 -0
@@ -294,3 +294,22 @@ bool strlazymatch(const char *str, const char *pat) {return __match_glob (str, pat, true); } + +/** +* strtailcmp - Compare the tail of two strings +* @s1: 1st string to be compared +* @s2: 2nd string to be compared +* +* Return 0 if whole of either string is same as another's tail part. +*/ +int strtailcmp (const char *s1,const char *s2) +{ +int i1 =strlen (s1); +int i2 =strlen (s2); +while (--i1 >=0 && --i2 >=0 ) { +if (s1[i1] != s2[i2]) +return s1[i1] - s2[i2]; + } +return 0 ; +} +
tools/perf/util/util.h +1 -0
@@ -238,6 +238,7 @@ char **argv_split(const char *str, int *argcp);void argv_free (char **argv);bool strglobmatch (const char *str,const char *pat);bool strlazymatch (const char *str,const char *pat); +int strtailcmp (const char *s1,const char *s2);unsigned long convert_unit (unsigned long value,char *unit);int readn (int fd,void *buf,size_t size);
[tip:perf/core] perf probe: Move strtailcmp to string.c
Commit-ID: bad03ae476214d9d66bb96be02b630385936f788 Gitweb: http://git.kernel.org/tip/bad03ae476214d9d66bb96be02b630385936f788 Author: Masami Hiramatsu <[email protected]> AuthorDate: Mon, 27 Jun 2011 16:27:15 +0900 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 15 Jul 2011 16:00:47 -0400
perf probe: Move strtailcmp to string.c
Since strtailcmp() is enough generic, it should be defined in string.c.
--- tools/perf/util/probe-finder.c | 15 --------------- tools/perf/util/string.c | 19 +++++++++++++++++++ tools/perf/util/util.h | 1 + 3 files changed, 20 insertions(+), 15 deletions(-)
tools/perf/util/probe-finder.c +0 -15
@@ -43,21 +43,6 @@/* Kprobe tracer basic type is up to u64 */ #define MAX_BASIC_TYPE_BITS 64 -/* -* Compare the tail of two strings. -* Return 0 if whole of either string is same as another's tail part. -*/ -static int strtailcmp (const char *s1,const char *s2) -{ -int i1 =strlen (s1); -int i2 =strlen (s2); -while (--i1 >=0 && --i2 >=0 ) { -if (s1[i1] != s2[i2]) -return s1[i1] - s2[i2]; - } -return 0 ; -} -/* Line number list operations */ /* Add a line to line number list */
tools/perf/util/string.c +19 -0
@@ -294,3 +294,22 @@ bool strlazymatch(const char *str, const char *pat) {return __match_glob (str, pat, true); } + +/** +* strtailcmp - Compare the tail of two strings +* @s1: 1st string to be compared +* @s2: 2nd string to be compared +* +* Return 0 if whole of either string is same as another's tail part. +*/ +int strtailcmp (const char *s1,const char *s2) +{ +int i1 =strlen (s1); +int i2 =strlen (s2); +while (--i1 >=0 && --i2 >=0 ) { +if (s1[i1] != s2[i2]) +return s1[i1] - s2[i2]; + } +return 0 ; +} +
tools/perf/util/util.h +1 -0
@@ -238,6 +238,7 @@ char **argv_split(const char *str, int *argcp);void argv_free (char **argv);bool strglobmatch (const char *str,const char *pat);bool strlazymatch (const char *str,const char *pat); +int strtailcmp (const char *s1,const char *s2);unsigned long convert_unit (unsigned long value,char *unit);int readn (int fd,void *buf,size_t size);
PATCH RESEND 8/13 perf probe: Remove redundant dwarf functions
In reply to Masami HiramatsuSince there are dwarf_bitsize, dwarf_bitoffset and dwarf_bytesize defined in libdw, we don't need die_get_bit_size, die_get_bit_offset and die_get_byte_size anymore.
---
tools/perf/util/probe-finder.c | 50 ++++++++++------------------------------ 1 files changed, 13 insertions(+), 37 deletions(-)
tools/perf/util/probe-finder.c +13 -37
@@ -361,36 +361,6 @@ static bool die_is_signed_type(Dwarf_Die *tp_die) ret == DW_ATE_signed_fixed); } -static int die_get_byte_size (Dwarf_Die *tp_die) -{ -Dwarf_Word ret; - -if (die_get_attr_udata (tp_die, DW_AT_byte_size, &ret)) -return 0 ; - -return (int )ret; -} - -static int die_get_bit_size (Dwarf_Die *tp_die) -{ -Dwarf_Word ret; - -if (die_get_attr_udata (tp_die, DW_AT_bit_size, &ret)) -return 0 ; - -return (int )ret; -} - -static int die_get_bit_offset (Dwarf_Die *tp_die) -{ -Dwarf_Word ret; - -if (die_get_attr_udata (tp_die, DW_AT_bit_offset, &ret)) -return 0 ; - -return (int )ret; -} -/* Get data_member_location offset */ static int die_get_data_member_location (Dwarf_Die *mb_die,Dwarf_Word *offs) {
@@ -882,6 +852,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,struct probe_trace_arg_ref **ref_ptr = &tvar->ref;Dwarf_Die type;char buf[16 ]; +int bsize, boffs, total;int ret;/* TODO: check all types */
@@ -891,11 +862,15 @@ static int convert_variable_type(Dwarf_Die *vr_die,return (tvar->type ==NULL ) ? -ENOMEM :0 ; } -if (die_get_bit_size (vr_die) !=0 ) { + bsize =dwarf_bitsize (vr_die); +if (bsize >0 ) {/* This is a bitfield */ - ret =snprintf (buf,16 ,"b%d@%d/%zd" ,die_get_bit_size (vr_die), -die_get_bit_offset (vr_die), -BYTES_TO_BITS (die_get_byte_size (vr_die))); + boffs =dwarf_bitoffset (vr_die); + total =dwarf_bytesize (vr_die); +if (boffs <0 || total <0 ) +return -ENOENT ; + ret =snprintf (buf,16 ,"b%d@%d/%zd" , bsize, boffs, +BYTES_TO_BITS (total)); goto formatted; }
@@ -943,10 +918,11 @@ static int convert_variable_type(Dwarf_Die *vr_die,return (tvar->type ==NULL ) ? -ENOMEM :0 ; } - ret =BYTES_TO_BITS (die_get_byte_size (&type)); -if (!ret) + ret =dwarf_bytesize (&type); +if (ret <=0 )/* No size ... try to use default type */ return 0 ; + ret =BYTES_TO_BITS (ret);/* Check the bitwidth */ if (ret >MAX_BASIC_TYPE_BITS ) {
@@ -1010,7 +986,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,else *ref_ptr = ref; } - ref->offset +=die_get_byte_size (&type) * field->index; + ref->offset +=dwarf_bytesize (&type) * field->index;if (!field->next)/* Save vr_die for converting types */ memcpy (die_mem, vr_die,sizeof (*die_mem));
[tip:perf/core] perf probe: Remove redundant dwarf functions
Commit-ID: bcfc082150c6b1e9443c1277bca8be80094150b5 Gitweb: http://git.kernel.org/tip/bcfc082150c6b1e9443c1277bca8be80094150b5 Author: Masami Hiramatsu <[email protected]> AuthorDate: Mon, 27 Jun 2011 16:27:21 +0900 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 15 Jul 2011 16:04:47 -0400
perf probe: Remove redundant dwarf functions
Since there are dwarf_bitsize, dwarf_bitoffset and dwarf_bytesize defined in libdw, we don't need die_get_bit_size, die_get_bit_offset and die_get_byte_size anymore.
--- tools/perf/util/probe-finder.c | 50 ++++++++++----------------------------- 1 files changed, 13 insertions(+), 37 deletions(-)
tools/perf/util/probe-finder.c +13 -37
@@ -361,36 +361,6 @@ static bool die_is_signed_type(Dwarf_Die *tp_die) ret == DW_ATE_signed_fixed); } -static int die_get_byte_size (Dwarf_Die *tp_die) -{ -Dwarf_Word ret; - -if (die_get_attr_udata (tp_die, DW_AT_byte_size, &ret)) -return 0 ; - -return (int )ret; -} - -static int die_get_bit_size (Dwarf_Die *tp_die) -{ -Dwarf_Word ret; - -if (die_get_attr_udata (tp_die, DW_AT_bit_size, &ret)) -return 0 ; - -return (int )ret; -} - -static int die_get_bit_offset (Dwarf_Die *tp_die) -{ -Dwarf_Word ret; - -if (die_get_attr_udata (tp_die, DW_AT_bit_offset, &ret)) -return 0 ; - -return (int )ret; -} -/* Get data_member_location offset */ static int die_get_data_member_location (Dwarf_Die *mb_die,Dwarf_Word *offs) {
@@ -882,6 +852,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,struct probe_trace_arg_ref **ref_ptr = &tvar->ref;Dwarf_Die type;char buf[16 ]; +int bsize, boffs, total;int ret;/* TODO: check all types */
@@ -891,11 +862,15 @@ static int convert_variable_type(Dwarf_Die *vr_die,return (tvar->type ==NULL ) ? -ENOMEM :0 ; } -if (die_get_bit_size (vr_die) !=0 ) { + bsize =dwarf_bitsize (vr_die); +if (bsize >0 ) {/* This is a bitfield */ - ret =snprintf (buf,16 ,"b%d@%d/%zd" ,die_get_bit_size (vr_die), -die_get_bit_offset (vr_die), -BYTES_TO_BITS (die_get_byte_size (vr_die))); + boffs =dwarf_bitoffset (vr_die); + total =dwarf_bytesize (vr_die); +if (boffs <0 || total <0 ) +return -ENOENT ; + ret =snprintf (buf,16 ,"b%d@%d/%zd" , bsize, boffs, +BYTES_TO_BITS (total)); goto formatted; }
@@ -943,10 +918,11 @@ static int convert_variable_type(Dwarf_Die *vr_die,return (tvar->type ==NULL ) ? -ENOMEM :0 ; } - ret =BYTES_TO_BITS (die_get_byte_size (&type)); -if (!ret) + ret =dwarf_bytesize (&type); +if (ret <=0 )/* No size ... try to use default type */ return 0 ; + ret =BYTES_TO_BITS (ret);/* Check the bitwidth */ if (ret >MAX_BASIC_TYPE_BITS ) {
@@ -1010,7 +986,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,else *ref_ptr = ref; } - ref->offset +=die_get_byte_size (&type) * field->index; + ref->offset +=dwarf_bytesize (&type) * field->index;if (!field->next)/* Save vr_die for converting types */ memcpy (die_mem, vr_die,sizeof (*die_mem));
PATCH RESEND 9/13 perf-probe: Move dwarf library routines to dwarf-aux.{c, h}
In reply to Masami HiramatsuMove dwarf library related routines to dwarf-aux.{c,h}. This includes several minor changes.
- Add simple documents for each API.
- Rename die_find_real_subprogram() to die_find_realfunc()
- Rename line_walk_handler_t to line_walk_callback_t.
- Minor cleanups.
---
tools/perf/Makefile | 2 tools/perf/util/dwarf-aux.c | 663 ++++++++++++++++++++++++++++++++++++++++ tools/perf/util/dwarf-aux.h | 100 ++++++ tools/perf/util/probe-finder.c | 520 ------------------------------- tools/perf/util/probe-finder.h | 6 5 files changed, 768 insertions(+), 523 deletions(-) create mode 100644 tools/perf/util/dwarf-aux.c create mode 100644 tools/perf/util/dwarf-aux.h
tools/perf/Makefile +2 -0
@@ -279,6 +279,7 @@ LIB_H += util/thread.h LIB_H += util/thread_map.h LIB_H += util/trace-event.h LIB_H += util/probe-finder.h +LIB_H += util/dwarf-aux.h LIB_H += util/probe-event.h LIB_H += util/pstack.h LIB_H += util/cpumap.h
@@ -435,6 +436,7 @@ else BASIC_CFLAGS += -DDWARF_SUPPORT EXTLIBS += -lelf -ldw LIB_OBJS += $(OUTPUT)util/probe-finder.o + LIB_OBJS += $(OUTPUT)util/dwarf-aux.o endif # PERF_HAVE_DWARF_REGS endif # NO_DWARF
tools/perf/util/dwarf-aux.c new file +663 -0
663 lines not on this page · raw message
tools/perf/util/dwarf-aux.h new file +100 -0
100 lines not on this page · raw message
tools/perf/util/probe-finder.c +2 -518
538 lines not on this page · raw message
tools/perf/util/probe-finder.h +1 -5
@@ -32,11 +32,7 @@ extern int find_line_range(int fd, struct line_range *lr);extern int find_available_vars_at (int fd,struct perf_probe_event *pev,struct variable_list **vls,int max_points,bool externs); - -#include <dwarf.h> -#include <elfutils/libdw.h> -#include <elfutils/libdwfl.h> -#include <elfutils/version.h> +#include "dwarf-aux.h" struct probe_finder {struct perf_probe_event *pev;/* Target probe event */
[tip:perf/core] perf-probe: Move dwarf library routines to dwarf-aux.{c, h}
Commit-ID: e0d153c69040bb37cbdf09deb52fee3013c07742 Gitweb: http://git.kernel.org/tip/e0d153c69040bb37cbdf09deb52fee3013c07742 Author: Masami Hiramatsu <[email protected]> AuthorDate: Mon, 27 Jun 2011 16:27:27 +0900 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 15 Jul 2011 16:10:17 -0400
perf-probe: Move dwarf library routines to dwarf-aux.{c, h}
Move dwarf library related routines to dwarf-aux.{c,h}. This includes several minor changes.
- Add simple documents for each API.
- Rename die_find_real_subprogram() to die_find_realfunc()
- Rename line_walk_handler_t to line_walk_callback_t.
- Minor cleanups.
--- tools/perf/Makefile | 2 + tools/perf/util/dwarf-aux.c | 663 ++++++++++++++++++++++++++++++++++++++++ tools/perf/util/dwarf-aux.h | 100 ++++++ tools/perf/util/probe-finder.c | 520 +------------------------------- tools/perf/util/probe-finder.h | 6 +- 5 files changed, 768 insertions(+), 523 deletions(-)
tools/perf/Makefile +2 -0
@@ -279,6 +279,7 @@ LIB_H += util/thread.h LIB_H += util/thread_map.h LIB_H += util/trace-event.h LIB_H += util/probe-finder.h +LIB_H += util/dwarf-aux.h LIB_H += util/probe-event.h LIB_H += util/pstack.h LIB_H += util/cpumap.h
@@ -435,6 +436,7 @@ else BASIC_CFLAGS += -DDWARF_SUPPORT EXTLIBS += -lelf -ldw LIB_OBJS += $(OUTPUT)util/probe-finder.o + LIB_OBJS += $(OUTPUT)util/dwarf-aux.o endif # PERF_HAVE_DWARF_REGS endif # NO_DWARF
tools/perf/util/dwarf-aux.c new file +663 -0
663 lines not on this page · raw message
tools/perf/util/dwarf-aux.h new file +100 -0
100 lines not on this page · raw message
tools/perf/util/probe-finder.c +2 -518
538 lines not on this page · raw message
tools/perf/util/probe-finder.h +1 -5
@@ -32,11 +32,7 @@ extern int find_line_range(int fd, struct line_range *lr);extern int find_available_vars_at (int fd,struct perf_probe_event *pev,struct variable_list **vls,int max_points,bool externs); - -#include <dwarf.h> -#include <elfutils/libdw.h> -#include <elfutils/libdwfl.h> -#include <elfutils/version.h> +#include "dwarf-aux.h" struct probe_finder {struct perf_probe_event *pev;/* Target probe event */
PATCH RESEND 10/13 perf probe: Warn when more than two lines are given
In reply to Masami HiramatsuPrint warning which warns only the last specified --line option is valid.
---
tools/perf/builtin-probe.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-)
tools/perf/builtin-probe.c +8 -3
@@ -134,10 +134,15 @@ static int opt_show_lines(const struct option *opt __used, {int ret =0 ; -if (str) - ret =parse_line_range_desc (str, ¶ms.line_range); -INIT_LIST_HEAD (¶ms.line_range.line_list); +if (!str) +return 0 ; + +if (params.show_lines) +pr_warning ("Warning: more than two --line option are" +" detected. Only last option is valid.\n" ); params.show_lines = true; + ret =parse_line_range_desc (str, ¶ms.line_range); +INIT_LIST_HEAD (¶ms.line_range.line_list);return ret; }
Re: [PATCH -tip 10/13] [RESEND]perf probe: Warn when more than two lines are given
Quoted 19 lines · Masami Hiramatsu
Print warning which warns only the last specified --line option is valid.
Signed-off-by Masami Hiramatsu <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Paul Mackerras <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>---
tools/perf/builtin-probe.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-)tools/perf/builtin-probe.c +0
-0@@ -134,10 +134,15 @@ static int opt_show_lines(const struct option *opt __used, {int ret =0 ;
tools/perf/builtin-probe.c static int opt_show_lines(const struct option *opt __used, · line 142
Quoted 10 lines
tools/perf/builtin-probe.c +6
-3-if (str) - ret =parse_line_range_desc (str, ¶ms.line_range); -INIT_LIST_HEAD (¶ms.line_range.line_list); +if (!str) +return 0 ; + +if (params.show_lines) +pr_warning ("Warning: more than two --line option are" +" detected. Only last option is valid.\n" );
This detects a second --line option, but your warning suggests two --line options are ok. Should that warning be "more than one --line option is"
David
Quoted 12 lines
tools/perf/builtin-probe.c +2
-1params.show_lines = true; + ret =parse_line_range_desc (str, ¶ms.line_range); +INIT_LIST_HEAD (¶ms.line_range.line_list);return ret; } --To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH -tip 10/13] [RESEND]perf probe: Warn when more than two lines are given
Quoted 23 lines · David Ahern
Quoted 20 lines · Masami Hiramatsu
Print warning which warns only the last specified --line option is valid.
Signed-off-by Masami Hiramatsu <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Paul Mackerras <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>---
tools/perf/builtin-probe.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-)tools/perf/builtin-probe.c +0
-0@@ -134,10 +134,15 @@ static int opt_show_lines(const struct option *opt __used, {int ret =0 ;
Quoted 13 lines
tools/perf/builtin-probe.c static int opt_show_lines(const struct option *opt __used, · line 142
Quoted 9 lines
tools/perf/builtin-probe.c +6
-3-if (str) - ret =parse_line_range_desc (str, ¶ms.line_range); -INIT_LIST_HEAD (¶ms.line_range.line_list); +if (!str) +return 0 ; + +if (params.show_lines) +pr_warning ("Warning: more than two --line option are" +" detected. Only last option is valid.\n" );This detects a second --line option, but your warning suggests two --line options are ok. Should that warning be "more than one --line option is"
Oops! Right, thank you!
Quoted 7 lines
Quoted 7 lines
tools/perf/builtin-probe.c +2
-0params.show_lines = true; + ret =parse_line_range_desc (str, ¶ms.line_range); +INIT_LIST_HEAD (¶ms.line_range.line_list);return ret; }
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
PATCH RESEND 11/13 perf probe: Introduce debuginfo to encapsulate dwarf information
In reply to Masami HiramatsuIntroduce debuginfo to encapsulate dwarf information. This new object allows us to reuse and expand debuginfo easily.
---
tools/perf/util/probe-event.c | 78 ++++++++++------ tools/perf/util/probe-finder.c | 201 +++++++++++++++++++++------------------- tools/perf/util/probe-finder.h | 39 ++++++-- 3 files changed, 182 insertions(+), 136 deletions(-)
tools/perf/util/probe-event.c +49 -29
@@ -170,16 +170,17 @@ const char *kernel_get_module_path(const char *module) }#ifdef DWARF_SUPPORT -static int open_vmlinux (const char *module) +/* Open new debuginfo of given module */ +static struct debuginfo *open_debuginfo (const char *module) {const char *path =kernel_get_module_path (module); +if (!path) {pr_err ("Failed to find path of %s module.\n" , module ?:"kernel" ); -return -ENOENT ; +return NULL ; } -pr_debug ("Try to open %s\n" , path); -return open (path,O_RDONLY ); +return debuginfo__new (path); }/*
@@ -193,13 +194,24 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,struct map *map;u64 addr;int ret = -ENOENT ; +struct debuginfo *dinfo; sym =__find_kernel_function_by_name (tp->symbol, &map);if (sym) { addr = map->unmap_ip (map, sym->start + tp->offset);pr_debug ("try to find %s+%ld@%" PRIx64"\n" , tp->symbol, tp->offset, addr); - ret =find_perf_probe_point ((unsigned long )addr, pp); + + dinfo =debuginfo__new_online_kernel (addr); +if (dinfo) { + ret =debuginfo__find_probe_point (dinfo, + (unsigned long )addr, pp); +debuginfo__delete (dinfo); + }else { +pr_debug ("Failed to open debuginfo at 0x%" PRIx64"\n" , + addr); + ret = -ENOENT ; + } }if (ret <=0 ) { pr_debug("Failed to find corresponding probes from "
@@ -220,20 +232,22 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, int max_tevs, const char *module) { bool need_dwarf = perf_probe_event_need_dwarf(pev); -int fd, ntevs; +struct debuginfo *dinfo =open_debuginfo (module); +int ntevs; - fd =open_vmlinux (module); -if (fd <0 ) { +if (!dinfo) {if (need_dwarf) {pr_warning ("Failed to open debuginfo file.\n" ); -return fd; +return -ENOENT ; } -pr_debug ("Could not open vmlinux. Try to use symbols.\n" ); +pr_debug ("Could not open debuginfo. Try to use symbols.\n" );return 0 ; } -/* Searching trace events corresponding to probe event */ - ntevs =find_probe_trace_events (fd, pev, tevs, max_tevs); +/* Searching trace events corresponding to a probe event */ + ntevs =debuginfo__find_trace_events (dinfo, pev, tevs, max_tevs); + +debuginfo__delete (dinfo);if (ntevs >0 ) {/* Succeeded to find trace events */ pr_debug ("find %d probe_trace_events.\n" , ntevs);
@@ -371,8 +385,9 @@ int show_line_range(struct line_range *lr, const char *module) {int l =1 ;struct line_node *ln; +struct debuginfo *dinfo;FILE *fp; -int fd, ret; +int ret;char *tmp;/* Search a line range */
@@ -380,13 +395,14 @@ int show_line_range(struct line_range *lr, const char *module)if (ret <0 )return ret; - fd =open_vmlinux (module); -if (fd <0 ) { + dinfo =open_debuginfo (module); +if (!dinfo) {pr_warning ("Failed to open debuginfo file.\n" ); -return fd; +return -ENOENT ; } - ret =find_line_range (fd, lr); + ret =debuginfo__find_line_range (dinfo, lr); +debuginfo__delete (dinfo);if (ret ==0 ) {pr_warning ("Specified source line is not found.\n" );return -ENOENT ;
@@ -448,7 +464,8 @@ end:return ret; } -static int show_available_vars_at (int fd,struct perf_probe_event *pev, +static int show_available_vars_at (struct debuginfo *dinfo, +struct perf_probe_event *pev,int max_vls,struct strfilter *_filter,bool externs) {
@@ -463,7 +480,8 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,return -EINVAL ;pr_debug ("Searching variables at %s\n" , buf); - ret =find_available_vars_at (fd, pev, &vls, max_vls, externs); + ret =debuginfo__find_available_vars_at (dinfo, pev, &vls, + max_vls, externs);if (ret <=0 ) {pr_err ("Failed to find variables at %s (%d)\n" , buf, ret); goto end;
@@ -504,24 +522,26 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, int max_vls, const char *module, struct strfilter *_filter, bool externs) { - int i, fd, ret = 0; + int i, ret = 0; +struct debuginfo *dinfo; ret =init_vmlinux ();if (ret <0 )return ret; + dinfo =open_debuginfo (module); +if (!dinfo) { +pr_warning ("Failed to open debuginfo file.\n" ); +return -ENOENT ; + } +setup_pager (); -for (i =0 ; i < npevs && ret >=0 ; i++) { - fd =open_vmlinux (module); -if (fd <0 ) { -pr_warning ("Failed to open debug information file.\n" ); - ret = fd; -break ; - } - ret =show_available_vars_at (fd, &pevs[i], max_vls, _filter, +for (i =0 ; i < npevs && ret >=0 ; i++) + ret =show_available_vars_at (dinfo, &pevs[i], max_vls, _filter, externs); - } + +debuginfo__delete (dinfo);return ret; }
tools/perf/util/probe-finder.c +104 -97
356 lines not on this page · raw message
tools/perf/util/probe-finder.h +29 -10
@@ -16,23 +16,42 @@ static inline int is_c_varname(const char *name) } #ifdef DWARF_SUPPORT + +#include "dwarf-aux.h" + +/* TODO: export debuginfo data structure even if no dwarf support */ + +/* debug information structure */ +struct debuginfo { + Dwarf *dbg; + Dwfl *dwfl; + Dwarf_Addr bias; +}; + +extern struct debuginfo *debuginfo__new(const char *path); +extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr); +extern void debuginfo__delete(struct debuginfo *self); + /* Find probe_trace_events specified by perf_probe_event from debuginfo */ -extern int find_probe_trace_events(int fd, struct perf_probe_event *pev, - struct probe_trace_event **tevs, - int max_tevs); +extern int debuginfo__find_trace_events(struct debuginfo *self, + struct perf_probe_event *pev, + struct probe_trace_event **tevs, + int max_tevs); /* Find a perf_probe_point from debuginfo */ -extern int find_perf_probe_point(unsigned long addr, - struct perf_probe_point *ppt); +extern int debuginfo__find_probe_point(struct debuginfo *self, + unsigned long addr, + struct perf_probe_point *ppt); /* Find a line range */ -extern int find_line_range(int fd, struct line_range *lr); +extern int debuginfo__find_line_range(struct debuginfo *self, + struct line_range *lr); /* Find available variables */ -extern int find_available_vars_at(int fd, struct perf_probe_event *pev, - struct variable_list **vls, int max_points, - bool externs); -#include "dwarf-aux.h" +extern int debuginfo__find_available_vars_at(struct debuginfo *self, + struct perf_probe_event *pev, + struct variable_list **vls, + int max_points, bool externs); struct probe_finder { struct perf_probe_event *pev; /* Target probe event */
[tip:perf/core] perf probe: Introduce debuginfo to encapsulate dwarf information
Commit-ID: ff741783506c340035659a71be68ddb4068760d1 Gitweb: http://git.kernel.org/tip/ff741783506c340035659a71be68ddb4068760d1 Author: Masami Hiramatsu <[email protected]> AuthorDate: Mon, 27 Jun 2011 16:27:39 +0900 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 15 Jul 2011 16:14:19 -0400
perf probe: Introduce debuginfo to encapsulate dwarf information
Introduce debuginfo to encapsulate dwarf information. This new object allows us to reuse and expand debuginfo easily.
--- tools/perf/util/probe-event.c | 78 ++++++++++------ tools/perf/util/probe-finder.c | 201 +++++++++++++++++++++------------------- tools/perf/util/probe-finder.h | 39 ++++++-- 3 files changed, 182 insertions(+), 136 deletions(-)
tools/perf/util/probe-event.c +49 -29
@@ -170,16 +170,17 @@ const char *kernel_get_module_path(const char *module) }#ifdef DWARF_SUPPORT -static int open_vmlinux (const char *module) +/* Open new debuginfo of given module */ +static struct debuginfo *open_debuginfo (const char *module) {const char *path =kernel_get_module_path (module); +if (!path) {pr_err ("Failed to find path of %s module.\n" , module ?:"kernel" ); -return -ENOENT ; +return NULL ; } -pr_debug ("Try to open %s\n" , path); -return open (path,O_RDONLY ); +return debuginfo__new (path); }/*
@@ -193,13 +194,24 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,struct map *map;u64 addr;int ret = -ENOENT ; +struct debuginfo *dinfo; sym =__find_kernel_function_by_name (tp->symbol, &map);if (sym) { addr = map->unmap_ip (map, sym->start + tp->offset);pr_debug ("try to find %s+%ld@%" PRIx64"\n" , tp->symbol, tp->offset, addr); - ret =find_perf_probe_point ((unsigned long )addr, pp); + + dinfo =debuginfo__new_online_kernel (addr); +if (dinfo) { + ret =debuginfo__find_probe_point (dinfo, + (unsigned long )addr, pp); +debuginfo__delete (dinfo); + }else { +pr_debug ("Failed to open debuginfo at 0x%" PRIx64"\n" , + addr); + ret = -ENOENT ; + } }if (ret <=0 ) { pr_debug("Failed to find corresponding probes from "
@@ -220,20 +232,22 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, int max_tevs, const char *module) { bool need_dwarf = perf_probe_event_need_dwarf(pev); -int fd, ntevs; +struct debuginfo *dinfo =open_debuginfo (module); +int ntevs; - fd =open_vmlinux (module); -if (fd <0 ) { +if (!dinfo) {if (need_dwarf) {pr_warning ("Failed to open debuginfo file.\n" ); -return fd; +return -ENOENT ; } -pr_debug ("Could not open vmlinux. Try to use symbols.\n" ); +pr_debug ("Could not open debuginfo. Try to use symbols.\n" );return 0 ; } -/* Searching trace events corresponding to probe event */ - ntevs =find_probe_trace_events (fd, pev, tevs, max_tevs); +/* Searching trace events corresponding to a probe event */ + ntevs =debuginfo__find_trace_events (dinfo, pev, tevs, max_tevs); + +debuginfo__delete (dinfo);if (ntevs >0 ) {/* Succeeded to find trace events */ pr_debug ("find %d probe_trace_events.\n" , ntevs);
@@ -371,8 +385,9 @@ int show_line_range(struct line_range *lr, const char *module) {int l =1 ;struct line_node *ln; +struct debuginfo *dinfo;FILE *fp; -int fd, ret; +int ret;char *tmp;/* Search a line range */
@@ -380,13 +395,14 @@ int show_line_range(struct line_range *lr, const char *module)if (ret <0 )return ret; - fd =open_vmlinux (module); -if (fd <0 ) { + dinfo =open_debuginfo (module); +if (!dinfo) {pr_warning ("Failed to open debuginfo file.\n" ); -return fd; +return -ENOENT ; } - ret =find_line_range (fd, lr); + ret =debuginfo__find_line_range (dinfo, lr); +debuginfo__delete (dinfo);if (ret ==0 ) {pr_warning ("Specified source line is not found.\n" );return -ENOENT ;
@@ -448,7 +464,8 @@ end:return ret; } -static int show_available_vars_at (int fd,struct perf_probe_event *pev, +static int show_available_vars_at (struct debuginfo *dinfo, +struct perf_probe_event *pev,int max_vls,struct strfilter *_filter,bool externs) {
@@ -463,7 +480,8 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,return -EINVAL ;pr_debug ("Searching variables at %s\n" , buf); - ret =find_available_vars_at (fd, pev, &vls, max_vls, externs); + ret =debuginfo__find_available_vars_at (dinfo, pev, &vls, + max_vls, externs);if (ret <=0 ) {pr_err ("Failed to find variables at %s (%d)\n" , buf, ret); goto end;
@@ -504,24 +522,26 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, int max_vls, const char *module, struct strfilter *_filter, bool externs) { - int i, fd, ret = 0; + int i, ret = 0; +struct debuginfo *dinfo; ret =init_vmlinux ();if (ret <0 )return ret; + dinfo =open_debuginfo (module); +if (!dinfo) { +pr_warning ("Failed to open debuginfo file.\n" ); +return -ENOENT ; + } +setup_pager (); -for (i =0 ; i < npevs && ret >=0 ; i++) { - fd =open_vmlinux (module); -if (fd <0 ) { -pr_warning ("Failed to open debug information file.\n" ); - ret = fd; -break ; - } - ret =show_available_vars_at (fd, &pevs[i], max_vls, _filter, +for (i =0 ; i < npevs && ret >=0 ; i++) + ret =show_available_vars_at (dinfo, &pevs[i], max_vls, _filter, externs); - } + +debuginfo__delete (dinfo);return ret; }
tools/perf/util/probe-finder.c +104 -97
356 lines not on this page · raw message
tools/perf/util/probe-finder.h +29 -10
@@ -16,23 +16,42 @@ static inline int is_c_varname(const char *name) } #ifdef DWARF_SUPPORT + +#include "dwarf-aux.h" + +/* TODO: export debuginfo data structure even if no dwarf support */ + +/* debug information structure */ +struct debuginfo { + Dwarf *dbg; + Dwfl *dwfl; + Dwarf_Addr bias; +}; + +extern struct debuginfo *debuginfo__new(const char *path); +extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr); +extern void debuginfo__delete(struct debuginfo *self); + /* Find probe_trace_events specified by perf_probe_event from debuginfo */ -extern int find_probe_trace_events(int fd, struct perf_probe_event *pev, - struct probe_trace_event **tevs, - int max_tevs); +extern int debuginfo__find_trace_events(struct debuginfo *self, + struct perf_probe_event *pev, + struct probe_trace_event **tevs, + int max_tevs); /* Find a perf_probe_point from debuginfo */ -extern int find_perf_probe_point(unsigned long addr, - struct perf_probe_point *ppt); +extern int debuginfo__find_probe_point(struct debuginfo *self, + unsigned long addr, + struct perf_probe_point *ppt); /* Find a line range */ -extern int find_line_range(int fd, struct line_range *lr); +extern int debuginfo__find_line_range(struct debuginfo *self, + struct line_range *lr); /* Find available variables */ -extern int find_available_vars_at(int fd, struct perf_probe_event *pev, - struct variable_list **vls, int max_points, - bool externs); -#include "dwarf-aux.h" +extern int debuginfo__find_available_vars_at(struct debuginfo *self, + struct perf_probe_event *pev, + struct variable_list **vls, + int max_points, bool externs); struct probe_finder { struct perf_probe_event *pev; /* Target probe event */
PATCH 12/13 perf probe: Add probed module in front of function
In reply to Masami HiramatsuAdd probed module name and ":" in front of function name if -m module option is given. In the result, the symbol name passed to kprobe-tracer becomes MODULE:FUNCTION, so that kallsyms can solve it as a symbol in the module correctly.
---
tools/perf/util/probe-event.c | 47 +++++++++++++++++++++++++++++++++-------- tools/perf/util/probe-event.h | 1 + 2 files changed, 39 insertions(+), 9 deletions(-)
tools/perf/util/probe-event.c +38 -9
@@ -226,14 +226,26 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,return 0 ; } +static int add_module_to_probe_trace_events (struct probe_trace_event *tevs, +int ntevs,const char *module) +{ +int i; +for (i =0 ; i < ntevs; i++) { + tevs[i].point.module =strdup (module); +if (!tevs[i].point.module) +return -ENOMEM ; + } +return 0 ; +} +/* Try to find perf_probe_event with debuginfo */ static int try_to_find_probe_trace_events (struct perf_probe_event *pev, -struct probe_trace_event **tevs, -int max_tevs,const char *module) +struct probe_trace_event **tevs, +int max_tevs,const char *module) {bool need_dwarf =perf_probe_event_need_dwarf (pev);struct debuginfo *dinfo =open_debuginfo (module); -int ntevs; +int ntevs, ret =0 ;if (!dinfo) {if (need_dwarf) {
@@ -251,7 +263,10 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,if (ntevs >0 ) {/* Succeeded to find trace events */ pr_debug ("find %d probe_trace_events.\n" , ntevs); -return ntevs; +if (module) + ret =add_module_to_probe_trace_events (*tevs, ntevs, + module); +return ret <0 ? ret : ntevs; }if (ntevs ==0 ) {/* No error but failed to find probe point. */
@@ -1010,7 +1025,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)/* Parse probe_events event into struct probe_point */ static int parse_probe_trace_command (const char *cmd, -struct probe_trace_event *tev) +struct probe_trace_event *tev) {struct probe_trace_point *tp = &tev->point;char pr;
@@ -1043,8 +1058,14 @@ static int parse_probe_trace_command(const char *cmd, tp->retprobe = (pr =='r' ); -/* Scan function name and offset */ - ret =sscanf (argv[1 ],"%a[^+]+%lu" , (float *)(void *)&tp->symbol, +/* Scan module name(if there), function name and offset */ + p =strchr (argv[1 ],':' ); +if (p) { + tp->module =strndup (argv[1 ], p - argv[1 ]); + p++; + }else + p = argv[1 ]; + ret =sscanf (p,"%a[^+]+%lu" , (float *)(void *)&tp->symbol, &tp->offset);if (ret ==1 ) tp->offset =0 ;
@@ -1289,9 +1310,10 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)if (buf ==NULL )return NULL ; - len =e_snprintf (buf,MAX_CMDLEN ,"%c:%s/%s %s+%lu" , + len =e_snprintf (buf,MAX_CMDLEN ,"%c:%s/%s %s%s%s+%lu" , tp->retprobe ?'r' :'p' , tev->group, tev->event, + tp->module ?:"" , tp->module ?":" :"" , tp->symbol, tp->offset);if (len <=0 ) goto error;
@@ -1398,6 +1420,8 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)free (tev->group);if (tev->point.symbol)free (tev->point.symbol); +if (tev->point.module) +free (tev->point.module);for (i =0 ; i < tev->nargs; i++) {if (tev->args[i].name)free (tev->args[i].name);
@@ -1749,7 +1773,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,/* Convert perf_probe_event with debuginfo */ ret =try_to_find_probe_trace_events (pev, tevs, max_tevs, module);if (ret !=0 ) -return ret; +return ret;/* Found in debuginfo or got an error */ /* Allocate trace event buffer */ tev = *tevs =zalloc (sizeof (struct probe_trace_event ));
@@ -1762,6 +1786,11 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, ret = -ENOMEM ; goto error; } + tev->point.module =strdup (module); +if (tev->point.module ==NULL ) { + ret = -ENOMEM ; + goto error; + } tev->point.offset = pev->point.offset; tev->point.retprobe = pev->point.retprobe; tev->nargs = pev->nargs;
tools/perf/util/probe-event.h +1 -0
@@ -10,6 +10,7 @@ extern bool probe_event_dry_run;/* kprobe-tracer tracing point */ struct probe_trace_point {char *symbol;/* Base symbol */ +char *module;/* Module name */ unsigned long offset;/* Offset from symbol */ bool retprobe;/* Return probe flag */ };
[tip:perf/core] perf probe: Add probed module in front of function
Commit-ID: 190b57fcb9c5fed5414935a174094f534fc510bc Gitweb: http://git.kernel.org/tip/190b57fcb9c5fed5414935a174094f534fc510bc Author: Masami Hiramatsu <[email protected]> AuthorDate: Mon, 27 Jun 2011 16:27:45 +0900 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 15 Jul 2011 16:19:08 -0400
perf probe: Add probed module in front of function
Add probed module name and ":" in front of function name if -m module option is given. In the result, the symbol name passed to kprobe-tracer becomes MODULE:FUNCTION, so that kallsyms can solve it as a symbol in the module correctly.
--- tools/perf/util/probe-event.c | 47 +++++++++++++++++++++++++++++++++------- tools/perf/util/probe-event.h | 1 + 2 files changed, 39 insertions(+), 9 deletions(-)
tools/perf/util/probe-event.c +38 -9
@@ -226,14 +226,26 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,return 0 ; } +static int add_module_to_probe_trace_events (struct probe_trace_event *tevs, +int ntevs,const char *module) +{ +int i; +for (i =0 ; i < ntevs; i++) { + tevs[i].point.module =strdup (module); +if (!tevs[i].point.module) +return -ENOMEM ; + } +return 0 ; +} +/* Try to find perf_probe_event with debuginfo */ static int try_to_find_probe_trace_events (struct perf_probe_event *pev, -struct probe_trace_event **tevs, -int max_tevs,const char *module) +struct probe_trace_event **tevs, +int max_tevs,const char *module) {bool need_dwarf =perf_probe_event_need_dwarf (pev);struct debuginfo *dinfo =open_debuginfo (module); -int ntevs; +int ntevs, ret =0 ;if (!dinfo) {if (need_dwarf) {
@@ -251,7 +263,10 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,if (ntevs >0 ) {/* Succeeded to find trace events */ pr_debug ("find %d probe_trace_events.\n" , ntevs); -return ntevs; +if (module) + ret =add_module_to_probe_trace_events (*tevs, ntevs, + module); +return ret <0 ? ret : ntevs; }if (ntevs ==0 ) {/* No error but failed to find probe point. */
@@ -1010,7 +1025,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)/* Parse probe_events event into struct probe_point */ static int parse_probe_trace_command (const char *cmd, -struct probe_trace_event *tev) +struct probe_trace_event *tev) {struct probe_trace_point *tp = &tev->point;char pr;
@@ -1043,8 +1058,14 @@ static int parse_probe_trace_command(const char *cmd, tp->retprobe = (pr =='r' ); -/* Scan function name and offset */ - ret =sscanf (argv[1 ],"%a[^+]+%lu" , (float *)(void *)&tp->symbol, +/* Scan module name(if there), function name and offset */ + p =strchr (argv[1 ],':' ); +if (p) { + tp->module =strndup (argv[1 ], p - argv[1 ]); + p++; + }else + p = argv[1 ]; + ret =sscanf (p,"%a[^+]+%lu" , (float *)(void *)&tp->symbol, &tp->offset);if (ret ==1 ) tp->offset =0 ;
@@ -1289,9 +1310,10 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)if (buf ==NULL )return NULL ; - len =e_snprintf (buf,MAX_CMDLEN ,"%c:%s/%s %s+%lu" , + len =e_snprintf (buf,MAX_CMDLEN ,"%c:%s/%s %s%s%s+%lu" , tp->retprobe ?'r' :'p' , tev->group, tev->event, + tp->module ?:"" , tp->module ?":" :"" , tp->symbol, tp->offset);if (len <=0 ) goto error;
@@ -1398,6 +1420,8 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)free (tev->group);if (tev->point.symbol)free (tev->point.symbol); +if (tev->point.module) +free (tev->point.module);for (i =0 ; i < tev->nargs; i++) {if (tev->args[i].name)free (tev->args[i].name);
@@ -1749,7 +1773,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,/* Convert perf_probe_event with debuginfo */ ret =try_to_find_probe_trace_events (pev, tevs, max_tevs, module);if (ret !=0 ) -return ret; +return ret;/* Found in debuginfo or got an error */ /* Allocate trace event buffer */ tev = *tevs =zalloc (sizeof (struct probe_trace_event ));
@@ -1762,6 +1786,11 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, ret = -ENOMEM ; goto error; } + tev->point.module =strdup (module); +if (tev->point.module ==NULL ) { + ret = -ENOMEM ; + goto error; + } tev->point.offset = pev->point.offset; tev->point.retprobe = pev->point.retprobe; tev->nargs = pev->nargs;
tools/perf/util/probe-event.h +1 -0
@@ -10,6 +10,7 @@ extern bool probe_event_dry_run;/* kprobe-tracer tracing point */ struct probe_trace_point {char *symbol;/* Base symbol */ +char *module;/* Module name */ unsigned long offset;/* Offset from symbol */ bool retprobe;/* Return probe flag */ };
PATCH 13/13 perf probe: Support adding probes on offline kernel modules
In reply to Masami HiramatsuSupport adding probes on offline kernel modules. This enables perf-probe to trace kernel-module init functions via perf-probe. If user gives the path of module with -m option, perf-probe expects the module is offline.
This feature works with --add, --funcs, and --vars.
E.g)
# perf probe -m /lib/modules/`uname -r`/kernel/fs/btrfs/btrfs.ko \ -a "extent_io_init:5 extent_state_cache" Add new events: probe:extent_io_init (on extent_io_init:5 with extent_state_cache) probe:extent_io_init_1 (on extent_io_init:5 with extent_state_cache)
You can now use it on all perf tools, such as:
perf record -e probe:extent_io_init_1 -aR sleep 1
---
tools/perf/Documentation/perf-probe.txt | 6 ++-- tools/perf/builtin-probe.c | 3 +- tools/perf/util/probe-event.c | 52 ++++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 12 deletions(-)
tools/perf/Documentation/perf-probe.txt +4 -2
@@ -34,9 +34,11 @@ OPTIONS Specify vmlinux path which has debuginfo (Dwarf binary). -m:: ---module=MODNAME:: +--module=MODNAME|PATH:: Specify module name in which perf-probe searches probe points - or lines. + or lines. If a path of module file is passed, perf-probe + treat it as an offline module (this means you can add a probe on + a module which has not been loaded yet). -s:: --source=PATH::
tools/perf/builtin-probe.c +2 -1
@@ -247,7 +247,8 @@ static const struct option options[] = {OPT_STRING ('s' ,"source" , &symbol_conf.source_prefix,"directory" ,"path to kernel source" ),OPT_STRING ('m' ,"module" , ¶ms.target_module, -"modname" ,"target module name" ), +"modname|path" , +"target module name (for online) or path (for offline)" ), #endifOPT__DRY_RUN (&probe_event_dry_run), OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points,
tools/perf/util/probe-event.c +43 -9
74 lines not on this page · raw message
[tip:perf/core] perf probe: Support adding probes on offline kernel modules
Commit-ID: 14a8fd7ceea6915c613746203d6e9a2bf273f16c Gitweb: http://git.kernel.org/tip/14a8fd7ceea6915c613746203d6e9a2bf273f16c Author: Masami Hiramatsu <[email protected]> AuthorDate: Mon, 27 Jun 2011 16:27:51 +0900 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 15 Jul 2011 16:25:12 -0400
perf probe: Support adding probes on offline kernel modules
Support adding probes on offline kernel modules. This enables perf-probe to trace kernel-module init functions via perf-probe. If user gives the path of module with -m option, perf-probe expects the module is offline.
This feature works with --add, --funcs, and --vars.
E.g)
# perf probe -m /lib/modules/`uname -r`/kernel/fs/btrfs/btrfs.ko \ -a "extent_io_init:5 extent_state_cache" Add new events: probe:extent_io_init (on extent_io_init:5 with extent_state_cache) probe:extent_io_init_1 (on extent_io_init:5 with extent_state_cache)
You can now use it on all perf tools, such as:
perf record -e probe:extent_io_init_1 -aR sleep 1
--- tools/perf/Documentation/perf-probe.txt | 6 ++- tools/perf/builtin-probe.c | 3 +- tools/perf/util/probe-event.c | 52 +++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 12 deletions(-)
tools/perf/Documentation/perf-probe.txt +4 -2
@@ -34,9 +34,11 @@ OPTIONS Specify vmlinux path which has debuginfo (Dwarf binary). -m:: ---module=MODNAME:: +--module=MODNAME|PATH:: Specify module name in which perf-probe searches probe points - or lines. + or lines. If a path of module file is passed, perf-probe + treat it as an offline module (this means you can add a probe on + a module which has not been loaded yet). -s:: --source=PATH::
tools/perf/builtin-probe.c +2 -1
@@ -242,7 +242,8 @@ static const struct option options[] = {OPT_STRING ('s' ,"source" , &symbol_conf.source_prefix,"directory" ,"path to kernel source" ),OPT_STRING ('m' ,"module" , ¶ms.target_module, -"modname" ,"target module name" ), +"modname|path" , +"target module name (for online) or path (for offline)" ), #endifOPT__DRY_RUN (&probe_event_dry_run), OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points,
tools/perf/util/probe-event.c +43 -9
74 lines not on this page · raw message
Steven Rostedt
maintainerQuoted 13 lines · Masami Hiramatsu
Hi Steven,
Here, I'd like to push updates of dynamic events and perf-probe for supporting dynamic events on module.
The main part of this series is 1-5th patches for kprobes and dynamic event tracer, which allows us to add events on offline kernel module. This means we can put events even on the init functions of the drivers before loading. The requirement of this feature comes from my recent experience of a driver debugging. It had a timing bug in the initialization routine, and it was hard to catch them without tracing the behavior.
Quoted 4 lines
I added some perf-probe updates (which including some resent patches), And it's OK to pull only the main part (kprobes and ftrace patches) without perf updates.
Thanks Masami,
I'll try to get to this this week. I've just been doing my main job at the moment ;) Which surprisingly, has nothing to do with ftrace.
-- Steve
Steven Rostedt
maintainerQuoted 13 lines · Masami Hiramatsu
Hi Steven,
Here, I'd like to push updates of dynamic events and perf-probe for supporting dynamic events on module.
The main part of this series is 1-5th patches for kprobes and dynamic event tracer, which allows us to add events on offline kernel module. This means we can put events even on the init functions of the drivers before loading. The requirement of this feature comes from my recent experience of a driver debugging. It had a timing bug in the initialization routine, and it was hard to catch them without tracing the behavior.
Quoted 4 lines
I added some perf-probe updates (which including some resent patches), And it's OK to pull only the main part (kprobes and ftrace patches) without perf updates.
OK I pulled in everything but patch 10, as that seemed to have an issue with the message that David Ahern brought up. I left that one out as it really wasn't necessary for the other patches. If you want to just resend that one patch with an update, I can pull that one in too.
-- Steve
Quoted 39 lines
Thank you,
---
Masami Hiramatsu (13):
perf probe: Support adding probes on offline kernel modules perf probe: Add probed module in front of function [RESEND]perf probe: Introduce debuginfo to encapsulate dwarf information [RESEND]perf probe: Warn when more than two lines are given [RESEND][CLEANUP]perf-probe: Move dwarf library routines to dwarf-aux.{c,h} [RESEND][CLEANUP]perf probe: Remove redundant dwarf functions [RESEND][CLEANUP]perf probe: Move strtailcmp tostring.c[RESEND][CLEANUP]perf probe: RenameDIE_FIND_CB_FOUNDtoDIE_FIND_CB_ENDtracing/kprobe: Update symbol reference when loading module tracing/kprobes: Support module init function probing
kprobes: Return-ENOENTif probe point doesn't exist [CLEANUP]tracing/kprobes: merge trace probe enable/disable functions [CLEANUP]tracing/kprobes: Rename probe_* to trace_probe_*Documentation/trace/kprobetrace.txt | 9 kernel/kprobes.c | 33 + kernel/trace/trace_kprobe.c | 314 +++++++++---- tools/perf/Documentation/perf-probe.txt | 6 tools/perf/Makefile | 2 tools/perf/builtin-probe.c | 14 - tools/perf/util/dwarf-aux.c | 663 +++++++++++++++++++++++++++ tools/perf/util/dwarf-aux.h | 100 ++++ tools/perf/util/probe-event.c | 165 +++++-- tools/perf/util/probe-event.h | 1 tools/perf/util/probe-finder.c | 752 ++++--------------------------- tools/perf/util/probe-finder.h | 43 +- tools/perf/util/string.c | 19 + tools/perf/util/util.h | 1 14 files changed, 1304 insertions(+), 818 deletions(-) create mode 100644 tools/perf/util/dwarf-aux.c create mode 100644 tools/perf/util/dwarf-aux.h
Quoted 19 lines · Steven Rostedt
Quoted 13 lines · Masami Hiramatsu
Hi Steven,
Here, I'd like to push updates of dynamic events and perf-probe for supporting dynamic events on module.
The main part of this series is 1-5th patches for kprobes and dynamic event tracer, which allows us to add events on offline kernel module. This means we can put events even on the init functions of the drivers before loading. The requirement of this feature comes from my recent experience of a driver debugging. It had a timing bug in the initialization routine, and it was hard to catch them without tracing the behavior.
Quoted 4 lines
I added some perf-probe updates (which including some resent patches), And it's OK to pull only the main part (kprobes and ftrace patches) without perf updates.
Quoted 4 lines
OK I pulled in everything but patch 10, as that seemed to have an issue with the message that David Ahern brought up. I left that one out as it really wasn't necessary for the other patches. If you want to just resend that one patch with an update, I can pull that one in too.
Thanks, and patch 10, I've found that that actually fixed a bug of perf probe itself and have sent it to Ingo as another bugfix, so feel free to drop it from your tree.
Thank you,
Quoted 49 lines
-- Steve
Quoted 30 lines
Thank you,
---
Masami Hiramatsu (13):
perf probe: Support adding probes on offline kernel modules perf probe: Add probed module in front of function [RESEND]perf probe: Introduce debuginfo to encapsulate dwarf information [RESEND]perf probe: Warn when more than two lines are given [RESEND][CLEANUP]perf-probe: Move dwarf library routines to dwarf-aux.{c,h} [RESEND][CLEANUP]perf probe: Remove redundant dwarf functions [RESEND][CLEANUP]perf probe: Move strtailcmp tostring.c[RESEND][CLEANUP]perf probe: RenameDIE_FIND_CB_FOUNDtoDIE_FIND_CB_ENDtracing/kprobe: Update symbol reference when loading module tracing/kprobes: Support module init function probing
kprobes: Return-ENOENTif probe point doesn't exist [CLEANUP]tracing/kprobes: merge trace probe enable/disable functions [CLEANUP]tracing/kprobes: Rename probe_* to trace_probe_*Documentation/trace/kprobetrace.txt | 9 kernel/kprobes.c | 33 + kernel/trace/trace_kprobe.c | 314 +++++++++---- tools/perf/Documentation/perf-probe.txt | 6 tools/perf/Makefile | 2 tools/perf/builtin-probe.c | 14 - tools/perf/util/dwarf-aux.c | 663 +++++++++++++++++++++++++++ tools/perf/util/dwarf-aux.h | 100 ++++ tools/perf/util/probe-event.c | 165 +++++--Quoted 9 lines
tools/perf/util/probe-event.h | 1 tools/perf/util/probe-finder.c | 752 ++++--------------------------- tools/perf/util/probe-finder.h | 43 +- tools/perf/util/string.c | 19 + tools/perf/util/util.h | 1 14 files changed, 1304 insertions(+), 818 deletions(-) create mode 100644 tools/perf/util/dwarf-aux.c create mode 100644 tools/perf/util/dwarf-aux.h--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]