aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_kprobe.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-02-28 13:17:55 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-02-28 13:17:55 -0500
commite0d272429a34ff143bfa04ee8e29dd4eed2964c7 (patch)
tree5a719135b245811b5d61ed084d7b8c1bc2e87031 /kernel/trace/trace_kprobe.c
parentd25e8dbdab203ed8b4fd0a174bb5259e35ecd87c (diff)
parent480917427b0b6ff39de55ffc81391055472e6c26 (diff)
Merge branch 'tracing-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'tracing-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (28 commits) ftrace: Add function names to dangling } in function graph tracer tracing: Simplify memory recycle of trace_define_field tracing: Remove unnecessary variable in print_graph_return tracing: Fix typo of info text in trace_kprobe.c tracing: Fix typo in prof_sysexit_enable() tracing: Remove CONFIG_TRACE_POWER from kernel config tracing: Fix ftrace_event_call alignment for use with gcc 4.5 ftrace: Remove memory barriers from NMI code when not needed tracing/kprobes: Add short documentation for HAVE_REGS_AND_STACK_ACCESS_API s390: Add pt_regs register and stack access API tracing/kprobes: Make Kconfig dependencies generic tracing: Unify arch_syscall_addr() implementations tracing: Add notrace to TRACE_EVENT implementation functions ftrace: Allow to remove a single function from function graph filter tracing: Add correct/incorrect to sort keys for branch annotation output tracing: Simplify test for function_graph tracing start point tracing: Drop the tr check from the graph tracing path tracing: Add stack dump to trace_printk if stacktrace option is set tracing: Use appropriate perl constructs in recordmcount.pl tracing: optimize recordmcount.pl for offsets-handling ...
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
-rw-r--r--kernel/trace/trace_kprobe.c108
1 files changed, 46 insertions, 62 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 50b1b8239806..465b36bef4ca 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -651,12 +651,12 @@ static int create_trace_probe(int argc, char **argv)
651 event = strchr(group, '/') + 1; 651 event = strchr(group, '/') + 1;
652 event[-1] = '\0'; 652 event[-1] = '\0';
653 if (strlen(group) == 0) { 653 if (strlen(group) == 0) {
654 pr_info("Group name is not specifiled\n"); 654 pr_info("Group name is not specified\n");
655 return -EINVAL; 655 return -EINVAL;
656 } 656 }
657 } 657 }
658 if (strlen(event) == 0) { 658 if (strlen(event) == 0) {
659 pr_info("Event name is not specifiled\n"); 659 pr_info("Event name is not specified\n");
660 return -EINVAL; 660 return -EINVAL;
661 } 661 }
662 } 662 }
@@ -1174,80 +1174,60 @@ static int kretprobe_event_define_fields(struct ftrace_event_call *event_call)
1174 return 0; 1174 return 0;
1175} 1175}
1176 1176
1177static int __probe_event_show_format(struct trace_seq *s, 1177static int __set_print_fmt(struct trace_probe *tp, char *buf, int len)
1178 struct trace_probe *tp, const char *fmt,
1179 const char *arg)
1180{ 1178{
1181 int i; 1179 int i;
1180 int pos = 0;
1182 1181
1183 /* Show format */ 1182 const char *fmt, *arg;
1184 if (!trace_seq_printf(s, "\nprint fmt: \"%s", fmt))
1185 return 0;
1186 1183
1187 for (i = 0; i < tp->nr_args; i++) 1184 if (!probe_is_return(tp)) {
1188 if (!trace_seq_printf(s, " %s=%%lx", tp->args[i].name)) 1185 fmt = "(%lx)";
1189 return 0; 1186 arg = "REC->" FIELD_STRING_IP;
1187 } else {
1188 fmt = "(%lx <- %lx)";
1189 arg = "REC->" FIELD_STRING_FUNC ", REC->" FIELD_STRING_RETIP;
1190 }
1190 1191
1191 if (!trace_seq_printf(s, "\", %s", arg)) 1192 /* When len=0, we just calculate the needed length */
1192 return 0; 1193#define LEN_OR_ZERO (len ? len - pos : 0)
1193 1194
1194 for (i = 0; i < tp->nr_args; i++) 1195 pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt);
1195 if (!trace_seq_printf(s, ", REC->%s", tp->args[i].name))
1196 return 0;
1197 1196
1198 return trace_seq_puts(s, "\n"); 1197 for (i = 0; i < tp->nr_args; i++) {
1199} 1198 pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%%lx",
1199 tp->args[i].name);
1200 }
1200 1201
1201#undef SHOW_FIELD 1202 pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg);
1202#define SHOW_FIELD(type, item, name) \
1203 do { \
1204 ret = trace_seq_printf(s, "\tfield:" #type " %s;\t" \
1205 "offset:%u;\tsize:%u;\tsigned:%d;\n", name,\
1206 (unsigned int)offsetof(typeof(field), item),\
1207 (unsigned int)sizeof(type), \
1208 is_signed_type(type)); \
1209 if (!ret) \
1210 return 0; \
1211 } while (0)
1212 1203
1213static int kprobe_event_show_format(struct ftrace_event_call *call, 1204 for (i = 0; i < tp->nr_args; i++) {
1214 struct trace_seq *s) 1205 pos += snprintf(buf + pos, LEN_OR_ZERO, ", REC->%s",
1215{ 1206 tp->args[i].name);
1216 struct kprobe_trace_entry field __attribute__((unused)); 1207 }
1217 int ret, i;
1218 struct trace_probe *tp = (struct trace_probe *)call->data;
1219
1220 SHOW_FIELD(unsigned long, ip, FIELD_STRING_IP);
1221 SHOW_FIELD(int, nargs, FIELD_STRING_NARGS);
1222 1208
1223 /* Show fields */ 1209#undef LEN_OR_ZERO
1224 for (i = 0; i < tp->nr_args; i++)
1225 SHOW_FIELD(unsigned long, args[i], tp->args[i].name);
1226 trace_seq_puts(s, "\n");
1227 1210
1228 return __probe_event_show_format(s, tp, "(%lx)", 1211 /* return the length of print_fmt */
1229 "REC->" FIELD_STRING_IP); 1212 return pos;
1230} 1213}
1231 1214
1232static int kretprobe_event_show_format(struct ftrace_event_call *call, 1215static int set_print_fmt(struct trace_probe *tp)
1233 struct trace_seq *s)
1234{ 1216{
1235 struct kretprobe_trace_entry field __attribute__((unused)); 1217 int len;
1236 int ret, i; 1218 char *print_fmt;
1237 struct trace_probe *tp = (struct trace_probe *)call->data;
1238 1219
1239 SHOW_FIELD(unsigned long, func, FIELD_STRING_FUNC); 1220 /* First: called with 0 length to calculate the needed length */
1240 SHOW_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP); 1221 len = __set_print_fmt(tp, NULL, 0);
1241 SHOW_FIELD(int, nargs, FIELD_STRING_NARGS); 1222 print_fmt = kmalloc(len + 1, GFP_KERNEL);
1223 if (!print_fmt)
1224 return -ENOMEM;
1242 1225
1243 /* Show fields */ 1226 /* Second: actually write the @print_fmt */
1244 for (i = 0; i < tp->nr_args; i++) 1227 __set_print_fmt(tp, print_fmt, len + 1);
1245 SHOW_FIELD(unsigned long, args[i], tp->args[i].name); 1228 tp->call.print_fmt = print_fmt;
1246 trace_seq_puts(s, "\n");
1247 1229
1248 return __probe_event_show_format(s, tp, "(%lx <- %lx)", 1230 return 0;
1249 "REC->" FIELD_STRING_FUNC
1250 ", REC->" FIELD_STRING_RETIP);
1251} 1231}
1252 1232
1253#ifdef CONFIG_EVENT_PROFILE 1233#ifdef CONFIG_EVENT_PROFILE
@@ -1448,18 +1428,20 @@ static int register_probe_event(struct trace_probe *tp)
1448 if (probe_is_return(tp)) { 1428 if (probe_is_return(tp)) {
1449 tp->event.trace = print_kretprobe_event; 1429 tp->event.trace = print_kretprobe_event;
1450 call->raw_init = probe_event_raw_init; 1430 call->raw_init = probe_event_raw_init;
1451 call->show_format = kretprobe_event_show_format;
1452 call->define_fields = kretprobe_event_define_fields; 1431 call->define_fields = kretprobe_event_define_fields;
1453 } else { 1432 } else {
1454 tp->event.trace = print_kprobe_event; 1433 tp->event.trace = print_kprobe_event;
1455 call->raw_init = probe_event_raw_init; 1434 call->raw_init = probe_event_raw_init;
1456 call->show_format = kprobe_event_show_format;
1457 call->define_fields = kprobe_event_define_fields; 1435 call->define_fields = kprobe_event_define_fields;
1458 } 1436 }
1437 if (set_print_fmt(tp) < 0)
1438 return -ENOMEM;
1459 call->event = &tp->event; 1439 call->event = &tp->event;
1460 call->id = register_ftrace_event(&tp->event); 1440 call->id = register_ftrace_event(&tp->event);
1461 if (!call->id) 1441 if (!call->id) {
1442 kfree(call->print_fmt);
1462 return -ENODEV; 1443 return -ENODEV;
1444 }
1463 call->enabled = 0; 1445 call->enabled = 0;
1464 call->regfunc = probe_event_enable; 1446 call->regfunc = probe_event_enable;
1465 call->unregfunc = probe_event_disable; 1447 call->unregfunc = probe_event_disable;
@@ -1472,6 +1454,7 @@ static int register_probe_event(struct trace_probe *tp)
1472 ret = trace_add_event_call(call); 1454 ret = trace_add_event_call(call);
1473 if (ret) { 1455 if (ret) {
1474 pr_info("Failed to register kprobe event: %s\n", call->name); 1456 pr_info("Failed to register kprobe event: %s\n", call->name);
1457 kfree(call->print_fmt);
1475 unregister_ftrace_event(&tp->event); 1458 unregister_ftrace_event(&tp->event);
1476 } 1459 }
1477 return ret; 1460 return ret;
@@ -1481,6 +1464,7 @@ static void unregister_probe_event(struct trace_probe *tp)
1481{ 1464{
1482 /* tp->event is unregistered in trace_remove_event_call() */ 1465 /* tp->event is unregistered in trace_remove_event_call() */
1483 trace_remove_event_call(&tp->call); 1466 trace_remove_event_call(&tp->call);
1467 kfree(tp->call.print_fmt);
1484} 1468}
1485 1469
1486/* Make a debugfs interface for controling probe points */ 1470/* Make a debugfs interface for controling probe points */