diff options
author | Srikar Dronamraju <srikar@linux.vnet.ibm.com> | 2012-04-11 06:30:43 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-05-07 08:30:17 -0400 |
commit | f3f096cfedf8113380c56fc855275cc75cd8cf55 (patch) | |
tree | b8d0553afc8cebf6dd320d094206e93df5d95794 /kernel/trace/trace_probe.c | |
parent | 8ab83f56475ec9151645a888dfe1941f4a92091d (diff) |
tracing: Provide trace events interface for uprobes
Implements trace_event support for uprobes. In its current form
it can be used to put probes at a specified offset in a file and
dump the required registers when the code flow reaches the
probed address.
The following example shows how to dump the instruction pointer
and %ax a register at the probed text address. Here we are
trying to probe zfree in /bin/zsh:
# cd /sys/kernel/debug/tracing/
# cat /proc/`pgrep zsh`/maps | grep /bin/zsh | grep r-xp
00400000-0048a000 r-xp 00000000 08:03 130904 /bin/zsh
# objdump -T /bin/zsh | grep -w zfree
0000000000446420 g DF .text 0000000000000012 Base
zfree # echo 'p /bin/zsh:0x46420 %ip %ax' > uprobe_events
# cat uprobe_events
p:uprobes/p_zsh_0x46420 /bin/zsh:0x0000000000046420
# echo 1 > events/uprobes/enable
# sleep 20
# echo 0 > events/uprobes/enable
# cat trace
# tracer: nop
#
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
zsh-24842 [006] 258544.995456: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79
zsh-24842 [007] 258545.000270: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79
zsh-24842 [002] 258545.043929: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79
zsh-24842 [004] 258547.046129: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79
Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Jim Keniston <jkenisto@linux.vnet.ibm.com>
Cc: Linux-mm <linux-mm@kvack.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: Anton Arapov <anton@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20120411103043.GB29437@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/trace/trace_probe.c')
-rw-r--r-- | kernel/trace/trace_probe.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 8e526b9286e9..daa9980153af 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c | |||
@@ -550,7 +550,7 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t, | |||
550 | 550 | ||
551 | /* Recursive argument parser */ | 551 | /* Recursive argument parser */ |
552 | static int parse_probe_arg(char *arg, const struct fetch_type *t, | 552 | static int parse_probe_arg(char *arg, const struct fetch_type *t, |
553 | struct fetch_param *f, bool is_return) | 553 | struct fetch_param *f, bool is_return, bool is_kprobe) |
554 | { | 554 | { |
555 | unsigned long param; | 555 | unsigned long param; |
556 | long offset; | 556 | long offset; |
@@ -558,6 +558,11 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t, | |||
558 | int ret; | 558 | int ret; |
559 | 559 | ||
560 | ret = 0; | 560 | ret = 0; |
561 | |||
562 | /* Until uprobe_events supports only reg arguments */ | ||
563 | if (!is_kprobe && arg[0] != '%') | ||
564 | return -EINVAL; | ||
565 | |||
561 | switch (arg[0]) { | 566 | switch (arg[0]) { |
562 | case '$': | 567 | case '$': |
563 | ret = parse_probe_vars(arg + 1, t, f, is_return); | 568 | ret = parse_probe_vars(arg + 1, t, f, is_return); |
@@ -619,7 +624,8 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t, | |||
619 | return -ENOMEM; | 624 | return -ENOMEM; |
620 | 625 | ||
621 | dprm->offset = offset; | 626 | dprm->offset = offset; |
622 | ret = parse_probe_arg(arg, t2, &dprm->orig, is_return); | 627 | ret = parse_probe_arg(arg, t2, &dprm->orig, is_return, |
628 | is_kprobe); | ||
623 | if (ret) | 629 | if (ret) |
624 | kfree(dprm); | 630 | kfree(dprm); |
625 | else { | 631 | else { |
@@ -677,7 +683,7 @@ static int __parse_bitfield_probe_arg(const char *bf, | |||
677 | 683 | ||
678 | /* String length checking wrapper */ | 684 | /* String length checking wrapper */ |
679 | int traceprobe_parse_probe_arg(char *arg, ssize_t *size, | 685 | int traceprobe_parse_probe_arg(char *arg, ssize_t *size, |
680 | struct probe_arg *parg, bool is_return) | 686 | struct probe_arg *parg, bool is_return, bool is_kprobe) |
681 | { | 687 | { |
682 | const char *t; | 688 | const char *t; |
683 | int ret; | 689 | int ret; |
@@ -703,7 +709,7 @@ int traceprobe_parse_probe_arg(char *arg, ssize_t *size, | |||
703 | } | 709 | } |
704 | parg->offset = *size; | 710 | parg->offset = *size; |
705 | *size += parg->type->size; | 711 | *size += parg->type->size; |
706 | ret = parse_probe_arg(arg, parg->type, &parg->fetch, is_return); | 712 | ret = parse_probe_arg(arg, parg->type, &parg->fetch, is_return, is_kprobe); |
707 | 713 | ||
708 | if (ret >= 0 && t != NULL) | 714 | if (ret >= 0 && t != NULL) |
709 | ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch); | 715 | ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch); |