aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_kprobe.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2009-09-10 19:53:38 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-09-11 00:08:00 -0400
commiteca0d916f6429785bbc88db3ff66631cde62b432 (patch)
treeba4ddf9900d128e7c8c24b6ee931eace0aad6a36 /kernel/trace/trace_kprobe.c
parente08d1c657f70bcaca11401cd6ac5c8fe59bd2bb7 (diff)
tracing/kprobes: Add argument name support
Add argument name assignment support and remove "alias" lines from format. This allows user to assign unique name to each argument. For example, $ echo p do_sys_open dfd=a0 filename=a1 flags=a2 mode=a3 > kprobe_events This assigns dfd, filename, flags, and mode to 1st - 4th arguments respectively. Trace buffer shows those names too. <...>-1439 [000] 1200885.933147: do_sys_open+0x0/0xdf: dfd=ffffff9c filename=bfa898ac flags=8000 mode=0 This helps users to know what each value means. Users can filter each events by these names too. Note that you can not filter by argN anymore. Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: Jim Keniston <jkenisto@us.ibm.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: Frank Ch. Eigler <fche@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Jason Baron <jbaron@redhat.com> Cc: K.Prasad <prasad@linux.vnet.ibm.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Tom Zanussi <tzanussi@gmail.com> LKML-Reference: <20090910235337.22412.77383.stgit@dhcp-100-2-132.bos.redhat.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
-rw-r--r--kernel/trace/trace_kprobe.c128
1 files changed, 64 insertions, 64 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 730e992d28da..44dad1aa95d3 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -176,9 +176,14 @@ static __kprobes void free_indirect_fetch_data(struct indirect_fetch_data *data)
176} 176}
177 177
178/** 178/**
179 * kprobe_trace_core 179 * Kprobe tracer core functions
180 */ 180 */
181 181
182struct probe_arg {
183 struct fetch_func fetch;
184 const char *name;
185};
186
182struct trace_probe { 187struct trace_probe {
183 struct list_head list; 188 struct list_head list;
184 struct kretprobe rp; /* Use rp.kp for kprobe use */ 189 struct kretprobe rp; /* Use rp.kp for kprobe use */
@@ -187,12 +192,12 @@ struct trace_probe {
187 struct ftrace_event_call call; 192 struct ftrace_event_call call;
188 struct trace_event event; 193 struct trace_event event;
189 unsigned int nr_args; 194 unsigned int nr_args;
190 struct fetch_func args[]; 195 struct probe_arg args[];
191}; 196};
192 197
193#define SIZEOF_TRACE_PROBE(n) \ 198#define SIZEOF_TRACE_PROBE(n) \
194 (offsetof(struct trace_probe, args) + \ 199 (offsetof(struct trace_probe, args) + \
195 (sizeof(struct fetch_func) * (n))) 200 (sizeof(struct probe_arg) * (n)))
196 201
197static int kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs); 202static int kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs);
198static int kretprobe_trace_func(struct kretprobe_instance *ri, 203static int kretprobe_trace_func(struct kretprobe_instance *ri,
@@ -301,15 +306,21 @@ error:
301 return ERR_PTR(-ENOMEM); 306 return ERR_PTR(-ENOMEM);
302} 307}
303 308
309static void free_probe_arg(struct probe_arg *arg)
310{
311 if (arg->fetch.func == fetch_symbol)
312 free_symbol_cache(arg->fetch.data);
313 else if (arg->fetch.func == fetch_indirect)
314 free_indirect_fetch_data(arg->fetch.data);
315 kfree(arg->name);
316}
317
304static void free_trace_probe(struct trace_probe *tp) 318static void free_trace_probe(struct trace_probe *tp)
305{ 319{
306 int i; 320 int i;
307 321
308 for (i = 0; i < tp->nr_args; i++) 322 for (i = 0; i < tp->nr_args; i++)
309 if (tp->args[i].func == fetch_symbol) 323 free_probe_arg(&tp->args[i]);
310 free_symbol_cache(tp->args[i].data);
311 else if (tp->args[i].func == fetch_indirect)
312 free_indirect_fetch_data(tp->args[i].data);
313 324
314 kfree(tp->call.name); 325 kfree(tp->call.name);
315 kfree(tp->symbol); 326 kfree(tp->symbol);
@@ -532,11 +543,13 @@ static int create_trace_probe(int argc, char **argv)
532 * %REG : fetch register REG 543 * %REG : fetch register REG
533 * Indirect memory fetch: 544 * Indirect memory fetch:
534 * +|-offs(ARG) : fetch memory at ARG +|- offs address. 545 * +|-offs(ARG) : fetch memory at ARG +|- offs address.
546 * Alias name of args:
547 * NAME=FETCHARG : set NAME as alias of FETCHARG.
535 */ 548 */
536 struct trace_probe *tp; 549 struct trace_probe *tp;
537 int i, ret = 0; 550 int i, ret = 0;
538 int is_return = 0; 551 int is_return = 0;
539 char *symbol = NULL, *event = NULL; 552 char *symbol = NULL, *event = NULL, *arg = NULL;
540 unsigned long offset = 0; 553 unsigned long offset = 0;
541 void *addr = NULL; 554 void *addr = NULL;
542 char buf[MAX_EVENT_NAME_LEN]; 555 char buf[MAX_EVENT_NAME_LEN];
@@ -596,12 +609,21 @@ static int create_trace_probe(int argc, char **argv)
596 /* parse arguments */ 609 /* parse arguments */
597 ret = 0; 610 ret = 0;
598 for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { 611 for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
599 if (strlen(argv[i]) > MAX_ARGSTR_LEN) { 612 /* Parse argument name */
600 pr_info("Argument%d(%s) is too long.\n", i, argv[i]); 613 arg = strchr(argv[i], '=');
614 if (arg)
615 *arg++ = '\0';
616 else
617 arg = argv[i];
618 tp->args[i].name = kstrdup(argv[i], GFP_KERNEL);
619
620 /* Parse fetch argument */
621 if (strlen(arg) > MAX_ARGSTR_LEN) {
622 pr_info("Argument%d(%s) is too long.\n", i, arg);
601 ret = -ENOSPC; 623 ret = -ENOSPC;
602 goto error; 624 goto error;
603 } 625 }
604 ret = parse_probe_arg(argv[i], &tp->args[i], is_return); 626 ret = parse_probe_arg(arg, &tp->args[i].fetch, is_return);
605 if (ret) 627 if (ret)
606 goto error; 628 goto error;
607 } 629 }
@@ -664,12 +686,12 @@ static int probes_seq_show(struct seq_file *m, void *v)
664 seq_printf(m, " 0x%p", tp->rp.kp.addr); 686 seq_printf(m, " 0x%p", tp->rp.kp.addr);
665 687
666 for (i = 0; i < tp->nr_args; i++) { 688 for (i = 0; i < tp->nr_args; i++) {
667 ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i]); 689 ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i].fetch);
668 if (ret < 0) { 690 if (ret < 0) {
669 pr_warning("Argument%d decoding error(%d).\n", i, ret); 691 pr_warning("Argument%d decoding error(%d).\n", i, ret);
670 return ret; 692 return ret;
671 } 693 }
672 seq_printf(m, " %s", buf); 694 seq_printf(m, " %s=%s", tp->args[i].name, buf);
673 } 695 }
674 seq_printf(m, "\n"); 696 seq_printf(m, "\n");
675 return 0; 697 return 0;
@@ -824,7 +846,7 @@ static __kprobes int kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs)
824 entry->nargs = tp->nr_args; 846 entry->nargs = tp->nr_args;
825 entry->ip = (unsigned long)kp->addr; 847 entry->ip = (unsigned long)kp->addr;
826 for (i = 0; i < tp->nr_args; i++) 848 for (i = 0; i < tp->nr_args; i++)
827 entry->args[i] = call_fetch(&tp->args[i], regs); 849 entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
828 850
829 if (!filter_current_check_discard(buffer, call, entry, event)) 851 if (!filter_current_check_discard(buffer, call, entry, event))
830 trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); 852 trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc);
@@ -858,7 +880,7 @@ static __kprobes int kretprobe_trace_func(struct kretprobe_instance *ri,
858 entry->func = (unsigned long)tp->rp.kp.addr; 880 entry->func = (unsigned long)tp->rp.kp.addr;
859 entry->ret_ip = (unsigned long)ri->ret_addr; 881 entry->ret_ip = (unsigned long)ri->ret_addr;
860 for (i = 0; i < tp->nr_args; i++) 882 for (i = 0; i < tp->nr_args; i++)
861 entry->args[i] = call_fetch(&tp->args[i], regs); 883 entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
862 884
863 if (!filter_current_check_discard(buffer, call, entry, event)) 885 if (!filter_current_check_discard(buffer, call, entry, event))
864 trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); 886 trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc);
@@ -872,9 +894,13 @@ print_kprobe_event(struct trace_iterator *iter, int flags)
872{ 894{
873 struct kprobe_trace_entry *field; 895 struct kprobe_trace_entry *field;
874 struct trace_seq *s = &iter->seq; 896 struct trace_seq *s = &iter->seq;
897 struct trace_event *event;
898 struct trace_probe *tp;
875 int i; 899 int i;
876 900
877 field = (struct kprobe_trace_entry *)iter->ent; 901 field = (struct kprobe_trace_entry *)iter->ent;
902 event = ftrace_find_event(field->ent.type);
903 tp = container_of(event, struct trace_probe, event);
878 904
879 if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET)) 905 if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET))
880 goto partial; 906 goto partial;
@@ -883,7 +909,8 @@ print_kprobe_event(struct trace_iterator *iter, int flags)
883 goto partial; 909 goto partial;
884 910
885 for (i = 0; i < field->nargs; i++) 911 for (i = 0; i < field->nargs; i++)
886 if (!trace_seq_printf(s, " 0x%lx", field->args[i])) 912 if (!trace_seq_printf(s, " %s=%lx",
913 tp->args[i].name, field->args[i]))
887 goto partial; 914 goto partial;
888 915
889 if (!trace_seq_puts(s, "\n")) 916 if (!trace_seq_puts(s, "\n"))
@@ -899,9 +926,13 @@ print_kretprobe_event(struct trace_iterator *iter, int flags)
899{ 926{
900 struct kretprobe_trace_entry *field; 927 struct kretprobe_trace_entry *field;
901 struct trace_seq *s = &iter->seq; 928 struct trace_seq *s = &iter->seq;
929 struct trace_event *event;
930 struct trace_probe *tp;
902 int i; 931 int i;
903 932
904 field = (struct kretprobe_trace_entry *)iter->ent; 933 field = (struct kretprobe_trace_entry *)iter->ent;
934 event = ftrace_find_event(field->ent.type);
935 tp = container_of(event, struct trace_probe, event);
905 936
906 if (!seq_print_ip_sym(s, field->ret_ip, flags | TRACE_ITER_SYM_OFFSET)) 937 if (!seq_print_ip_sym(s, field->ret_ip, flags | TRACE_ITER_SYM_OFFSET))
907 goto partial; 938 goto partial;
@@ -916,7 +947,8 @@ print_kretprobe_event(struct trace_iterator *iter, int flags)
916 goto partial; 947 goto partial;
917 948
918 for (i = 0; i < field->nargs; i++) 949 for (i = 0; i < field->nargs; i++)
919 if (!trace_seq_printf(s, " 0x%lx", field->args[i])) 950 if (!trace_seq_printf(s, " %s=%lx",
951 tp->args[i].name, field->args[i]))
920 goto partial; 952 goto partial;
921 953
922 if (!trace_seq_puts(s, "\n")) 954 if (!trace_seq_puts(s, "\n"))
@@ -972,7 +1004,6 @@ static int kprobe_event_define_fields(struct ftrace_event_call *event_call)
972{ 1004{
973 int ret, i; 1005 int ret, i;
974 struct kprobe_trace_entry field; 1006 struct kprobe_trace_entry field;
975 char buf[MAX_ARGSTR_LEN + 1];
976 struct trace_probe *tp = (struct trace_probe *)event_call->data; 1007 struct trace_probe *tp = (struct trace_probe *)event_call->data;
977 1008
978 ret = trace_define_common_fields(event_call); 1009 ret = trace_define_common_fields(event_call);
@@ -981,16 +1012,9 @@ static int kprobe_event_define_fields(struct ftrace_event_call *event_call)
981 1012
982 DEFINE_FIELD(unsigned long, ip, "ip", 0); 1013 DEFINE_FIELD(unsigned long, ip, "ip", 0);
983 DEFINE_FIELD(int, nargs, "nargs", 1); 1014 DEFINE_FIELD(int, nargs, "nargs", 1);
984 for (i = 0; i < tp->nr_args; i++) { 1015 /* Set argument names as fields */
985 /* Set argN as a field */ 1016 for (i = 0; i < tp->nr_args; i++)
986 sprintf(buf, "arg%d", i); 1017 DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0);
987 DEFINE_FIELD(unsigned long, args[i], buf, 0);
988 /* Set argument string as an alias field */
989 ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i]);
990 if (ret < 0)
991 return ret;
992 DEFINE_FIELD(unsigned long, args[i], buf, 0);
993 }
994 return 0; 1018 return 0;
995} 1019}
996 1020
@@ -998,7 +1022,6 @@ static int kretprobe_event_define_fields(struct ftrace_event_call *event_call)
998{ 1022{
999 int ret, i; 1023 int ret, i;
1000 struct kretprobe_trace_entry field; 1024 struct kretprobe_trace_entry field;
1001 char buf[MAX_ARGSTR_LEN + 1];
1002 struct trace_probe *tp = (struct trace_probe *)event_call->data; 1025 struct trace_probe *tp = (struct trace_probe *)event_call->data;
1003 1026
1004 ret = trace_define_common_fields(event_call); 1027 ret = trace_define_common_fields(event_call);
@@ -1008,16 +1031,9 @@ static int kretprobe_event_define_fields(struct ftrace_event_call *event_call)
1008 DEFINE_FIELD(unsigned long, func, "func", 0); 1031 DEFINE_FIELD(unsigned long, func, "func", 0);
1009 DEFINE_FIELD(unsigned long, ret_ip, "ret_ip", 0); 1032 DEFINE_FIELD(unsigned long, ret_ip, "ret_ip", 0);
1010 DEFINE_FIELD(int, nargs, "nargs", 1); 1033 DEFINE_FIELD(int, nargs, "nargs", 1);
1011 for (i = 0; i < tp->nr_args; i++) { 1034 /* Set argument names as fields */
1012 /* Set argN as a field */ 1035 for (i = 0; i < tp->nr_args; i++)
1013 sprintf(buf, "arg%d", i); 1036 DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0);
1014 DEFINE_FIELD(unsigned long, args[i], buf, 0);
1015 /* Set argument string as an alias field */
1016 ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i]);
1017 if (ret < 0)
1018 return ret;
1019 DEFINE_FIELD(unsigned long, args[i], buf, 0);
1020 }
1021 return 0; 1037 return 0;
1022} 1038}
1023 1039
@@ -1025,31 +1041,21 @@ static int __probe_event_show_format(struct trace_seq *s,
1025 struct trace_probe *tp, const char *fmt, 1041 struct trace_probe *tp, const char *fmt,
1026 const char *arg) 1042 const char *arg)
1027{ 1043{
1028 int i, ret; 1044 int i;
1029 char buf[MAX_ARGSTR_LEN + 1];
1030 1045
1031 /* Show aliases */
1032 for (i = 0; i < tp->nr_args; i++) {
1033 ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i]);
1034 if (ret < 0)
1035 return ret;
1036 if (!trace_seq_printf(s, "\talias: %s;\toriginal: arg%d;\n",
1037 buf, i))
1038 return 0;
1039 }
1040 /* Show format */ 1046 /* Show format */
1041 if (!trace_seq_printf(s, "\nprint fmt: \"%s", fmt)) 1047 if (!trace_seq_printf(s, "\nprint fmt: \"%s", fmt))
1042 return 0; 1048 return 0;
1043 1049
1044 for (i = 0; i < tp->nr_args; i++) 1050 for (i = 0; i < tp->nr_args; i++)
1045 if (!trace_seq_puts(s, " 0x%lx")) 1051 if (!trace_seq_printf(s, " %s=%%lx", tp->args[i].name))
1046 return 0; 1052 return 0;
1047 1053
1048 if (!trace_seq_printf(s, "\", %s", arg)) 1054 if (!trace_seq_printf(s, "\", %s", arg))
1049 return 0; 1055 return 0;
1050 1056
1051 for (i = 0; i < tp->nr_args; i++) 1057 for (i = 0; i < tp->nr_args; i++)
1052 if (!trace_seq_printf(s, ", arg%d", i)) 1058 if (!trace_seq_printf(s, ", REC->%s", tp->args[i].name))
1053 return 0; 1059 return 0;
1054 1060
1055 return trace_seq_puts(s, "\n"); 1061 return trace_seq_puts(s, "\n");
@@ -1071,17 +1077,14 @@ static int kprobe_event_show_format(struct ftrace_event_call *call,
1071{ 1077{
1072 struct kprobe_trace_entry field __attribute__((unused)); 1078 struct kprobe_trace_entry field __attribute__((unused));
1073 int ret, i; 1079 int ret, i;
1074 char buf[8];
1075 struct trace_probe *tp = (struct trace_probe *)call->data; 1080 struct trace_probe *tp = (struct trace_probe *)call->data;
1076 1081
1077 SHOW_FIELD(unsigned long, ip, "ip"); 1082 SHOW_FIELD(unsigned long, ip, "ip");
1078 SHOW_FIELD(int, nargs, "nargs"); 1083 SHOW_FIELD(int, nargs, "nargs");
1079 1084
1080 /* Show fields */ 1085 /* Show fields */
1081 for (i = 0; i < tp->nr_args; i++) { 1086 for (i = 0; i < tp->nr_args; i++)
1082 sprintf(buf, "arg%d", i); 1087 SHOW_FIELD(unsigned long, args[i], tp->args[i].name);
1083 SHOW_FIELD(unsigned long, args[i], buf);
1084 }
1085 trace_seq_puts(s, "\n"); 1088 trace_seq_puts(s, "\n");
1086 1089
1087 return __probe_event_show_format(s, tp, "%lx:", "ip"); 1090 return __probe_event_show_format(s, tp, "%lx:", "ip");
@@ -1092,7 +1095,6 @@ static int kretprobe_event_show_format(struct ftrace_event_call *call,
1092{ 1095{
1093 struct kretprobe_trace_entry field __attribute__((unused)); 1096 struct kretprobe_trace_entry field __attribute__((unused));
1094 int ret, i; 1097 int ret, i;
1095 char buf[8];
1096 struct trace_probe *tp = (struct trace_probe *)call->data; 1098 struct trace_probe *tp = (struct trace_probe *)call->data;
1097 1099
1098 SHOW_FIELD(unsigned long, func, "func"); 1100 SHOW_FIELD(unsigned long, func, "func");
@@ -1100,10 +1102,8 @@ static int kretprobe_event_show_format(struct ftrace_event_call *call,
1100 SHOW_FIELD(int, nargs, "nargs"); 1102 SHOW_FIELD(int, nargs, "nargs");
1101 1103
1102 /* Show fields */ 1104 /* Show fields */
1103 for (i = 0; i < tp->nr_args; i++) { 1105 for (i = 0; i < tp->nr_args; i++)
1104 sprintf(buf, "arg%d", i); 1106 SHOW_FIELD(unsigned long, args[i], tp->args[i].name);
1105 SHOW_FIELD(unsigned long, args[i], buf);
1106 }
1107 trace_seq_puts(s, "\n"); 1107 trace_seq_puts(s, "\n");
1108 1108
1109 return __probe_event_show_format(s, tp, "%lx <- %lx:", 1109 return __probe_event_show_format(s, tp, "%lx <- %lx:",
@@ -1140,7 +1140,7 @@ static __kprobes int kprobe_profile_func(struct kprobe *kp,
1140 entry->nargs = tp->nr_args; 1140 entry->nargs = tp->nr_args;
1141 entry->ip = (unsigned long)kp->addr; 1141 entry->ip = (unsigned long)kp->addr;
1142 for (i = 0; i < tp->nr_args; i++) 1142 for (i = 0; i < tp->nr_args; i++)
1143 entry->args[i] = call_fetch(&tp->args[i], regs); 1143 entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
1144 perf_tpcounter_event(call->id, entry->ip, 1, entry, size); 1144 perf_tpcounter_event(call->id, entry->ip, 1, entry, size);
1145 } while (0); 1145 } while (0);
1146 return 0; 1146 return 0;
@@ -1175,7 +1175,7 @@ static __kprobes int kretprobe_profile_func(struct kretprobe_instance *ri,
1175 entry->func = (unsigned long)tp->rp.kp.addr; 1175 entry->func = (unsigned long)tp->rp.kp.addr;
1176 entry->ret_ip = (unsigned long)ri->ret_addr; 1176 entry->ret_ip = (unsigned long)ri->ret_addr;
1177 for (i = 0; i < tp->nr_args; i++) 1177 for (i = 0; i < tp->nr_args; i++)
1178 entry->args[i] = call_fetch(&tp->args[i], regs); 1178 entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
1179 perf_tpcounter_event(call->id, entry->ret_ip, 1, entry, size); 1179 perf_tpcounter_event(call->id, entry->ret_ip, 1, entry, size);
1180 } while (0); 1180 } while (0);
1181 return 0; 1181 return 0;