aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib/traceevent/event-parse.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-11 20:06:34 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-11 20:06:34 -0500
commitad5d69899e52792671c1aa6c7360464c7edfe09c (patch)
tree21833c1fdab4b3cf791d4fdc86dd578e4a620514 /tools/lib/traceevent/event-parse.c
parentef1417a5a6a400dbc1a2f44da716ab146a29ddc4 (diff)
parentcaea6cf52139116e43e615d87fcbf9823e197fdf (diff)
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar: "As a first remark I'd like to note that the way to build perf tooling has been simplified and sped up, in the future it should be enough for you to build perf via: cd tools/perf/ make install (ie without the -j option.) The build system will figure out the number of CPUs and will do a parallel build+install. The various build system inefficiencies and breakages Linus reported against the v3.12 pull request should now be resolved - please (re-)report any remaining annoyances or bugs. Main changes on the perf kernel side: * Performance optimizations: . perf ring-buffer code optimizations, by Peter Zijlstra . perf ring-buffer code optimizations, by Oleg Nesterov . x86 NMI call-stack processing optimizations, by Peter Zijlstra . perf context-switch optimizations, by Peter Zijlstra . perf sampling speedups, by Peter Zijlstra . x86 Intel PEBS processing speedups, by Peter Zijlstra * Enhanced hardware support: . for Intel Ivy Bridge-EP uncore PMUs, by Zheng Yan . for Haswell transactions, by Andi Kleen, Peter Zijlstra * Core perf events code enhancements and fixes by Oleg Nesterov: . for uprobes, if fork() is called with pending ret-probes . for uprobes platform support code * New ABI details by Andi Kleen: . Report x86 Haswell TSX transaction abort cost as weight Main changes on the perf tooling side (some of these tooling changes utilize the above kernel side changes): * 'perf report/top' enhancements: . Convert callchain children list to rbtree, greatly reducing the time taken for callchain processing, from Namhyung Kim. . Add new COMM infrastructure, further improving histogram processing, from Frédéric Weisbecker, one fix from Namhyung Kim. . Add /proc/kcore based live-annotation improvements, including build-id cache support, multi map 'call' instruction navigation fixes, kcore address validation, objdump workarounds. From Adrian Hunter. . Show progress on histogram collapsing, that can take a long time, from Namhyung Kim. . Add --max-stack option to limit callchain stack scan in 'top' and 'report', improving callchain processing when reducing the stack depth is an option, from Waiman Long. . Add new option --ignore-vmlinux for perf top, from Willy Tarreau. * 'perf trace' enhancements: . 'perf trace' now can can use a 'perf probe' dynamic tracepoints to hook into the userspace -> kernel pathname copy so that it can map fds to pathnames without reading /proc/pid/fd/ symlinks. From Arnaldo Carvalho de Melo. . Show VFS path associated with fd in live sessions, using a 'vfs_getname' 'perf probe' created dynamic tracepoint or by looking at /proc/pid/fd, from Arnaldo Carvalho de Melo. . Add 'trace' beautifiers for lots of syscall arguments, from Arnaldo Carvalho de Melo. . Implement more compact 'trace' output by suppressing zeroed args, from Arnaldo Carvalho de Melo. . Show thread COMM by default in 'trace', from Arnaldo Carvalho de Melo. . Add option to show full timestamp in 'trace', from David Ahern. . Add 'record' command in 'trace', to record raw_syscalls:*, from David Ahern. . Add summary option to dump syscall statistics in 'trace', from David Ahern. . Improve error messages in 'trace', providing hints about system configuration steps needed for using it, from Ramkumar Ramachandra. . 'perf trace' now emits hints as to why tracing is not possible, helping the user to setup the system to allow tracing in the desired permission granularity, telling if the problem is due to debugfs not being mounted or with not enough permission for !root, /proc/sys/kernel/perf_event_paranoit value, etc. From Arnaldo Carvalho de Melo. * 'perf record' enhancements: . Check maximum frequency rate for record/top, emitting better error messages, from Jiri Olsa. . 'perf record' code cleanups, from David Ahern. . Improve write_output error message in 'perf record', from Adrian Hunter. . Allow specifying B/K/M/G unit to the --mmap-pages arguments, from Jiri Olsa. . Fix command line callchain attribute tests to handle the new -g/--call-chain semantics, from Arnaldo Carvalho de Melo. * 'perf kvm' enhancements: . Disable live kvm command if timerfd is not supported, from David Ahern. . Fix detection of non-core features, from David Ahern. * 'perf list' enhancements: . Add usage to 'perf list', from David Ahern. . Show error in 'perf list' if tracepoints not available, from Pekka Enberg. * 'perf probe' enhancements: . Support "$vars" meta argument syntax for local variables, allowing asking for all possible variables at a given probe point to be collected when it hits, from Masami Hiramatsu. * 'perf sched' enhancements: . Address the root cause of that 'perf sched' stack initialization build slowdown, by programmatically setting a big array after moving the global variable back to the stack. Fix from Adrian Hunter. * 'perf script' enhancements: . Set up output options for in-stream attributes, from Adrian Hunter. . Print addr by default for BTS in 'perf script', from Adrian Juntmer * 'perf stat' enhancements: . Improved messages when doing profiling in all or a subset of CPUs using a workload as the session delimitator, as in: 'perf stat --cpu 0,2 sleep 10s' from Arnaldo Carvalho de Melo. . Add units to nanosec-based counters in 'perf stat', from David Ahern. . Remove bogus info when using 'perf stat' -e cycles/instructions, from Ramkumar Ramachandra. * 'perf lock' enhancements: . 'perf lock' fixes and cleanups, from Davidlohr Bueso. * 'perf test' enhancements: . Fixup PERF_SAMPLE_TRANSACTION handling in sample synthesizing and 'perf test', from Adrian Hunter. . Clarify the "sample parsing" test entry, from Arnaldo Carvalho de Melo. . Consider PERF_SAMPLE_TRANSACTION in the "sample parsing" test, from Arnaldo Carvalho de Melo. . Memory leak fixes in 'perf test', from Felipe Pena. * 'perf bench' enhancements: . Change the procps visible command-name of invididual benchmark tests plus cleanups, from Ingo Molnar. * Generic perf tooling infrastructure/plumbing changes: . Separating data file properties from session, code reorganization from Jiri Olsa. . Fix version when building out of tree, as when using one of these: $ make help | grep perf perf-tar-src-pkg - Build perf-3.12.0.tar source tarball perf-targz-src-pkg - Build perf-3.12.0.tar.gz source tarball perf-tarbz2-src-pkg - Build perf-3.12.0.tar.bz2 source tarball perf-tarxz-src-pkg - Build perf-3.12.0.tar.xz source tarball $ from David Ahern. . Enhance option parse error message, showing just the help lines of the options affected, from Namhyung Kim. . libtraceevent updates from upstream trace-cmd repo, from Steven Rostedt. . Always use perf_evsel__set_sample_bit to set sample_type, from Adrian Hunter. . Memory and mmap leak fixes from Chenggang Qin. . Assorted build fixes for from David Ahern and Jiri Olsa. . Speed up and prettify the build system, from Ingo Molnar. . Implement addr2line directly using libbfd, from Roberto Vitillo. . Separate the GTK support in a separate libperf-gtk.so DSO, that is only loaded when --gtk is specified, from Namhyung Kim. . perf bash completion fixes and improvements from Ramkumar Ramachandra. . Support for Openembedded/Yocto -dbg packages, from Ricardo Ribalda Delgado. And lots and lots of other fixes and code reorganizations that did not make it into the list, see the shortlog, diffstat and the Git log for details!" * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (300 commits) uprobes: Fix the memory out of bound overwrite in copy_insn() uprobes: Fix the wrong usage of current->utask in uprobe_copy_process() perf tools: Remove unneeded include perf record: Remove post_processing_offset variable perf record: Remove advance_output function perf record: Refactor feature handling into a separate function perf trace: Don't relookup fields by name in each sample perf tools: Fix version when building out of tree perf evsel: Ditch evsel->handler.data field uprobes: Export write_opcode() as uprobe_write_opcode() uprobes: Introduce arch_uprobe->ixol uprobes: Kill module_init() and module_exit() uprobes: Move function declarations out of arch perf/x86/intel: Add Ivy Bridge-EP uncore IRP box support perf/x86/intel/uncore: Add filter support for IvyBridge-EP QPI boxes perf: Factor out strncpy() in perf_event_mmap_event() tools/perf: Add required memory barriers perf: Fix arch_perf_out_copy_user default perf: Update a stale comment perf: Optimize perf_output_begin() -- address calculation ...
Diffstat (limited to 'tools/lib/traceevent/event-parse.c')
-rw-r--r--tools/lib/traceevent/event-parse.c165
1 files changed, 124 insertions, 41 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index d1c2a6a4cd32..8f450adaa9c2 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -305,6 +305,11 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
305 return 0; 305 return 0;
306} 306}
307 307
308void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock)
309{
310 pevent->trace_clock = trace_clock;
311}
312
308struct func_map { 313struct func_map {
309 unsigned long long addr; 314 unsigned long long addr;
310 char *func; 315 char *func;
@@ -599,10 +604,11 @@ find_printk(struct pevent *pevent, unsigned long long addr)
599 * This registers a string by the address it was stored in the kernel. 604 * This registers a string by the address it was stored in the kernel.
600 * The @fmt passed in is duplicated. 605 * The @fmt passed in is duplicated.
601 */ 606 */
602int pevent_register_print_string(struct pevent *pevent, char *fmt, 607int pevent_register_print_string(struct pevent *pevent, const char *fmt,
603 unsigned long long addr) 608 unsigned long long addr)
604{ 609{
605 struct printk_list *item = malloc(sizeof(*item)); 610 struct printk_list *item = malloc(sizeof(*item));
611 char *p;
606 612
607 if (!item) 613 if (!item)
608 return -1; 614 return -1;
@@ -610,10 +616,21 @@ int pevent_register_print_string(struct pevent *pevent, char *fmt,
610 item->next = pevent->printklist; 616 item->next = pevent->printklist;
611 item->addr = addr; 617 item->addr = addr;
612 618
619 /* Strip off quotes and '\n' from the end */
620 if (fmt[0] == '"')
621 fmt++;
613 item->printk = strdup(fmt); 622 item->printk = strdup(fmt);
614 if (!item->printk) 623 if (!item->printk)
615 goto out_free; 624 goto out_free;
616 625
626 p = item->printk + strlen(item->printk) - 1;
627 if (*p == '"')
628 *p = 0;
629
630 p -= 2;
631 if (strcmp(p, "\\n") == 0)
632 *p = 0;
633
617 pevent->printklist = item; 634 pevent->printklist = item;
618 pevent->printk_count++; 635 pevent->printk_count++;
619 636
@@ -3488,6 +3505,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3488 struct pevent *pevent = event->pevent; 3505 struct pevent *pevent = event->pevent;
3489 struct print_flag_sym *flag; 3506 struct print_flag_sym *flag;
3490 struct format_field *field; 3507 struct format_field *field;
3508 struct printk_map *printk;
3491 unsigned long long val, fval; 3509 unsigned long long val, fval;
3492 unsigned long addr; 3510 unsigned long addr;
3493 char *str; 3511 char *str;
@@ -3523,7 +3541,12 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3523 if (!(field->flags & FIELD_IS_ARRAY) && 3541 if (!(field->flags & FIELD_IS_ARRAY) &&
3524 field->size == pevent->long_size) { 3542 field->size == pevent->long_size) {
3525 addr = *(unsigned long *)(data + field->offset); 3543 addr = *(unsigned long *)(data + field->offset);
3526 trace_seq_printf(s, "%lx", addr); 3544 /* Check if it matches a print format */
3545 printk = find_printk(pevent, addr);
3546 if (printk)
3547 trace_seq_puts(s, printk->printk);
3548 else
3549 trace_seq_printf(s, "%lx", addr);
3527 break; 3550 break;
3528 } 3551 }
3529 str = malloc(len + 1); 3552 str = malloc(len + 1);
@@ -3565,15 +3588,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3565 } 3588 }
3566 break; 3589 break;
3567 case PRINT_HEX: 3590 case PRINT_HEX:
3568 field = arg->hex.field->field.field; 3591 if (arg->hex.field->type == PRINT_DYNAMIC_ARRAY) {
3569 if (!field) { 3592 unsigned long offset;
3570 str = arg->hex.field->field.name; 3593 offset = pevent_read_number(pevent,
3571 field = pevent_find_any_field(event, str); 3594 data + arg->hex.field->dynarray.field->offset,
3572 if (!field) 3595 arg->hex.field->dynarray.field->size);
3573 goto out_warning_field; 3596 hex = data + (offset & 0xffff);
3574 arg->hex.field->field.field = field; 3597 } else {
3598 field = arg->hex.field->field.field;
3599 if (!field) {
3600 str = arg->hex.field->field.name;
3601 field = pevent_find_any_field(event, str);
3602 if (!field)
3603 goto out_warning_field;
3604 arg->hex.field->field.field = field;
3605 }
3606 hex = data + field->offset;
3575 } 3607 }
3576 hex = data + field->offset;
3577 len = eval_num_arg(data, size, event, arg->hex.size); 3608 len = eval_num_arg(data, size, event, arg->hex.size);
3578 for (i = 0; i < len; i++) { 3609 for (i = 0; i < len; i++) {
3579 if (i) 3610 if (i)
@@ -3771,8 +3802,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3771 if (asprintf(&arg->atom.atom, "%lld", ip) < 0) 3802 if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
3772 goto out_free; 3803 goto out_free;
3773 3804
3774 /* skip the first "%pf : " */ 3805 /* skip the first "%pf: " */
3775 for (ptr = fmt + 6, bptr = data + field->offset; 3806 for (ptr = fmt + 5, bptr = data + field->offset;
3776 bptr < data + size && *ptr; ptr++) { 3807 bptr < data + size && *ptr; ptr++) {
3777 int ls = 0; 3808 int ls = 0;
3778 3809
@@ -3882,7 +3913,6 @@ get_bprint_format(void *data, int size __maybe_unused,
3882 struct format_field *field; 3913 struct format_field *field;
3883 struct printk_map *printk; 3914 struct printk_map *printk;
3884 char *format; 3915 char *format;
3885 char *p;
3886 3916
3887 field = pevent->bprint_fmt_field; 3917 field = pevent->bprint_fmt_field;
3888 3918
@@ -3899,25 +3929,13 @@ get_bprint_format(void *data, int size __maybe_unused,
3899 3929
3900 printk = find_printk(pevent, addr); 3930 printk = find_printk(pevent, addr);
3901 if (!printk) { 3931 if (!printk) {
3902 if (asprintf(&format, "%%pf : (NO FORMAT FOUND at %llx)\n", addr) < 0) 3932 if (asprintf(&format, "%%pf: (NO FORMAT FOUND at %llx)\n", addr) < 0)
3903 return NULL; 3933 return NULL;
3904 return format; 3934 return format;
3905 } 3935 }
3906 3936
3907 p = printk->printk; 3937 if (asprintf(&format, "%s: %s", "%pf", printk->printk) < 0)
3908 /* Remove any quotes. */
3909 if (*p == '"')
3910 p++;
3911 if (asprintf(&format, "%s : %s", "%pf", p) < 0)
3912 return NULL; 3938 return NULL;
3913 /* remove ending quotes and new line since we will add one too */
3914 p = format + strlen(format) - 1;
3915 if (*p == '"')
3916 *p = 0;
3917
3918 p -= 2;
3919 if (strcmp(p, "\\n") == 0)
3920 *p = 0;
3921 3939
3922 return format; 3940 return format;
3923} 3941}
@@ -3963,7 +3981,7 @@ static int is_printable_array(char *p, unsigned int len)
3963 unsigned int i; 3981 unsigned int i;
3964 3982
3965 for (i = 0; i < len && p[i]; i++) 3983 for (i = 0; i < len && p[i]; i++)
3966 if (!isprint(p[i])) 3984 if (!isprint(p[i]) && !isspace(p[i]))
3967 return 0; 3985 return 0;
3968 return 1; 3986 return 1;
3969} 3987}
@@ -4428,11 +4446,11 @@ void pevent_event_info(struct trace_seq *s, struct event_format *event,
4428{ 4446{
4429 int print_pretty = 1; 4447 int print_pretty = 1;
4430 4448
4431 if (event->pevent->print_raw) 4449 if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW))
4432 print_event_fields(s, record->data, record->size, event); 4450 print_event_fields(s, record->data, record->size, event);
4433 else { 4451 else {
4434 4452
4435 if (event->handler) 4453 if (event->handler && !(event->flags & EVENT_FL_NOHANDLE))
4436 print_pretty = event->handler(s, record, event, 4454 print_pretty = event->handler(s, record, event,
4437 event->context); 4455 event->context);
4438 4456
@@ -4443,8 +4461,21 @@ void pevent_event_info(struct trace_seq *s, struct event_format *event,
4443 trace_seq_terminate(s); 4461 trace_seq_terminate(s);
4444} 4462}
4445 4463
4464static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock)
4465{
4466 if (!use_trace_clock)
4467 return true;
4468
4469 if (!strcmp(trace_clock, "local") || !strcmp(trace_clock, "global")
4470 || !strcmp(trace_clock, "uptime") || !strcmp(trace_clock, "perf"))
4471 return true;
4472
4473 /* trace_clock is setting in tsc or counter mode */
4474 return false;
4475}
4476
4446void pevent_print_event(struct pevent *pevent, struct trace_seq *s, 4477void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
4447 struct pevent_record *record) 4478 struct pevent_record *record, bool use_trace_clock)
4448{ 4479{
4449 static const char *spaces = " "; /* 20 spaces */ 4480 static const char *spaces = " "; /* 20 spaces */
4450 struct event_format *event; 4481 struct event_format *event;
@@ -4457,9 +4488,14 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
4457 int pid; 4488 int pid;
4458 int len; 4489 int len;
4459 int p; 4490 int p;
4491 bool use_usec_format;
4460 4492
4461 secs = record->ts / NSECS_PER_SEC; 4493 use_usec_format = is_timestamp_in_us(pevent->trace_clock,
4462 nsecs = record->ts - secs * NSECS_PER_SEC; 4494 use_trace_clock);
4495 if (use_usec_format) {
4496 secs = record->ts / NSECS_PER_SEC;
4497 nsecs = record->ts - secs * NSECS_PER_SEC;
4498 }
4463 4499
4464 if (record->size < 0) { 4500 if (record->size < 0) {
4465 do_warning("ug! negative record size %d", record->size); 4501 do_warning("ug! negative record size %d", record->size);
@@ -4484,15 +4520,20 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
4484 } else 4520 } else
4485 trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu); 4521 trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
4486 4522
4487 if (pevent->flags & PEVENT_NSEC_OUTPUT) { 4523 if (use_usec_format) {
4488 usecs = nsecs; 4524 if (pevent->flags & PEVENT_NSEC_OUTPUT) {
4489 p = 9; 4525 usecs = nsecs;
4490 } else { 4526 p = 9;
4491 usecs = (nsecs + 500) / NSECS_PER_USEC; 4527 } else {
4492 p = 6; 4528 usecs = (nsecs + 500) / NSECS_PER_USEC;
4493 } 4529 p = 6;
4530 }
4494 4531
4495 trace_seq_printf(s, " %5lu.%0*lu: %s: ", secs, p, usecs, event->name); 4532 trace_seq_printf(s, " %5lu.%0*lu: %s: ",
4533 secs, p, usecs, event->name);
4534 } else
4535 trace_seq_printf(s, " %12llu: %s: ",
4536 record->ts, event->name);
4496 4537
4497 /* Space out the event names evenly. */ 4538 /* Space out the event names evenly. */
4498 len = strlen(event->name); 4539 len = strlen(event->name);
@@ -5326,6 +5367,48 @@ int pevent_print_num_field(struct trace_seq *s, const char *fmt,
5326 return -1; 5367 return -1;
5327} 5368}
5328 5369
5370/**
5371 * pevent_print_func_field - print a field and a format for function pointers
5372 * @s: The seq to print to
5373 * @fmt: The printf format to print the field with.
5374 * @event: the event that the field is for
5375 * @name: The name of the field
5376 * @record: The record with the field name.
5377 * @err: print default error if failed.
5378 *
5379 * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
5380 */
5381int pevent_print_func_field(struct trace_seq *s, const char *fmt,
5382 struct event_format *event, const char *name,
5383 struct pevent_record *record, int err)
5384{
5385 struct format_field *field = pevent_find_field(event, name);
5386 struct pevent *pevent = event->pevent;
5387 unsigned long long val;
5388 struct func_map *func;
5389 char tmp[128];
5390
5391 if (!field)
5392 goto failed;
5393
5394 if (pevent_read_number_field(field, record->data, &val))
5395 goto failed;
5396
5397 func = find_func(pevent, val);
5398
5399 if (func)
5400 snprintf(tmp, 128, "%s/0x%llx", func->func, func->addr - val);
5401 else
5402 sprintf(tmp, "0x%08llx", val);
5403
5404 return trace_seq_printf(s, fmt, tmp);
5405
5406 failed:
5407 if (err)
5408 trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
5409 return -1;
5410}
5411
5329static void free_func_handle(struct pevent_function_handler *func) 5412static void free_func_handle(struct pevent_function_handler *func)
5330{ 5413{
5331 struct pevent_func_params *params; 5414 struct pevent_func_params *params;