aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-kmem.txt13
-rw-r--r--tools/perf/Documentation/perf-probe.txt21
-rw-r--r--tools/perf/builtin-buildid-list.c2
-rw-r--r--tools/perf/builtin-kmem.c123
-rw-r--r--tools/perf/builtin-probe.c80
-rw-r--r--tools/perf/builtin-report.c39
-rw-r--r--tools/perf/builtin-sched.c212
-rw-r--r--tools/perf/builtin-timechart.c54
-rw-r--r--tools/perf/builtin-trace.c48
-rw-r--r--tools/perf/util/data_map.c4
-rw-r--r--tools/perf/util/data_map.h2
-rw-r--r--tools/perf/util/event.c67
-rw-r--r--tools/perf/util/event.h17
-rw-r--r--tools/perf/util/header.c9
-rw-r--r--tools/perf/util/parse-events.c17
-rw-r--r--tools/perf/util/parse-options.c3
-rw-r--r--tools/perf/util/probe-event.c133
-rw-r--r--tools/perf/util/probe-event.h1
-rw-r--r--tools/perf/util/probe-finder.c2
-rw-r--r--tools/perf/util/symbol.c5
-rw-r--r--tools/perf/util/trace-event-parse.c4
-rw-r--r--tools/perf/util/trace-event-perl.c67
-rw-r--r--tools/perf/util/trace-event-perl.h4
-rw-r--r--tools/perf/util/trace-event-read.c3
24 files changed, 578 insertions, 352 deletions
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt
index 44b0ce35c28a..eac4d852e7cd 100644
--- a/tools/perf/Documentation/perf-kmem.txt
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -8,16 +8,16 @@ perf-kmem - Tool to trace/measure kernel memory(slab) properties
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf kmem' {record} [<options>] 11'perf kmem' {record|stat} [<options>]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15There's two variants of perf kmem: 15There are two variants of perf kmem:
16 16
17 'perf kmem record <command>' to record the kmem events 17 'perf kmem record <command>' to record the kmem events
18 of an arbitrary workload. 18 of an arbitrary workload.
19 19
20 'perf kmem' to report kernel memory statistics. 20 'perf kmem stat' to report kernel memory statistics.
21 21
22OPTIONS 22OPTIONS
23------- 23-------
@@ -25,8 +25,11 @@ OPTIONS
25--input=<file>:: 25--input=<file>::
26 Select the input file (default: perf.data) 26 Select the input file (default: perf.data)
27 27
28--stat=<caller|alloc>:: 28--caller::
29 Select per callsite or per allocation statistics 29 Show per-callsite statistics
30
31--alloc::
32 Show per-allocation statistics
30 33
31-s <key[,key2...]>:: 34-s <key[,key2...]>::
32--sort=<key[,key2...]>:: 35--sort=<key[,key2...]>::
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 9270594e6dfd..8fa6bf99fcb5 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -8,10 +8,13 @@ perf-probe - Define new dynamic tracepoints
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf probe' [options] --add 'PROBE' [--add 'PROBE' ...] 11'perf probe' [options] --add='PROBE' [...]
12or 12or
13'perf probe' [options] 'PROBE' ['PROBE' ...] 13'perf probe' [options] PROBE
14 14or
15'perf probe' [options] --del='[GROUP:]EVENT' [...]
16or
17'perf probe' --list
15 18
16DESCRIPTION 19DESCRIPTION
17----------- 20-----------
@@ -31,8 +34,16 @@ OPTIONS
31 Be more verbose (show parsed arguments, etc). 34 Be more verbose (show parsed arguments, etc).
32 35
33-a:: 36-a::
34--add:: 37--add=::
35 Define a probe point (see PROBE SYNTAX for detail) 38 Define a probe event (see PROBE SYNTAX for detail).
39
40-d::
41--del=::
42 Delete a probe event.
43
44-l::
45--list::
46 List up current probe events.
36 47
37PROBE SYNTAX 48PROBE SYNTAX
38------------ 49------------
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 7dee9d19ab7a..dcb6143a0002 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -19,7 +19,7 @@ static char const *input_name = "perf.data";
19static int force; 19static int force;
20 20
21static const char *const buildid_list_usage[] = { 21static const char *const buildid_list_usage[] = {
22 "perf report [<options>]", 22 "perf buildid-list [<options>]",
23 NULL 23 NULL
24}; 24};
25 25
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 047fef74bd52..5f209514f657 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -57,11 +57,6 @@ static struct rb_root root_caller_sorted;
57static unsigned long total_requested, total_allocated; 57static unsigned long total_requested, total_allocated;
58static unsigned long nr_allocs, nr_cross_allocs; 58static unsigned long nr_allocs, nr_cross_allocs;
59 59
60struct raw_event_sample {
61 u32 size;
62 char data[0];
63};
64
65#define PATH_SYS_NODE "/sys/devices/system/node" 60#define PATH_SYS_NODE "/sys/devices/system/node"
66 61
67static void init_cpunode_map(void) 62static void init_cpunode_map(void)
@@ -201,7 +196,7 @@ static void insert_caller_stat(unsigned long call_site,
201 } 196 }
202} 197}
203 198
204static void process_alloc_event(struct raw_event_sample *raw, 199static void process_alloc_event(void *data,
205 struct event *event, 200 struct event *event,
206 int cpu, 201 int cpu,
207 u64 timestamp __used, 202 u64 timestamp __used,
@@ -214,10 +209,10 @@ static void process_alloc_event(struct raw_event_sample *raw,
214 int bytes_alloc; 209 int bytes_alloc;
215 int node1, node2; 210 int node1, node2;
216 211
217 ptr = raw_field_value(event, "ptr", raw->data); 212 ptr = raw_field_value(event, "ptr", data);
218 call_site = raw_field_value(event, "call_site", raw->data); 213 call_site = raw_field_value(event, "call_site", data);
219 bytes_req = raw_field_value(event, "bytes_req", raw->data); 214 bytes_req = raw_field_value(event, "bytes_req", data);
220 bytes_alloc = raw_field_value(event, "bytes_alloc", raw->data); 215 bytes_alloc = raw_field_value(event, "bytes_alloc", data);
221 216
222 insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, cpu); 217 insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, cpu);
223 insert_caller_stat(call_site, bytes_req, bytes_alloc); 218 insert_caller_stat(call_site, bytes_req, bytes_alloc);
@@ -227,7 +222,7 @@ static void process_alloc_event(struct raw_event_sample *raw,
227 222
228 if (node) { 223 if (node) {
229 node1 = cpunode_map[cpu]; 224 node1 = cpunode_map[cpu];
230 node2 = raw_field_value(event, "node", raw->data); 225 node2 = raw_field_value(event, "node", data);
231 if (node1 != node2) 226 if (node1 != node2)
232 nr_cross_allocs++; 227 nr_cross_allocs++;
233 } 228 }
@@ -262,7 +257,7 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr,
262 return NULL; 257 return NULL;
263} 258}
264 259
265static void process_free_event(struct raw_event_sample *raw, 260static void process_free_event(void *data,
266 struct event *event, 261 struct event *event,
267 int cpu, 262 int cpu,
268 u64 timestamp __used, 263 u64 timestamp __used,
@@ -271,7 +266,7 @@ static void process_free_event(struct raw_event_sample *raw,
271 unsigned long ptr; 266 unsigned long ptr;
272 struct alloc_stat *s_alloc, *s_caller; 267 struct alloc_stat *s_alloc, *s_caller;
273 268
274 ptr = raw_field_value(event, "ptr", raw->data); 269 ptr = raw_field_value(event, "ptr", data);
275 270
276 s_alloc = search_alloc_stat(ptr, 0, &root_alloc_stat, ptr_cmp); 271 s_alloc = search_alloc_stat(ptr, 0, &root_alloc_stat, ptr_cmp);
277 if (!s_alloc) 272 if (!s_alloc)
@@ -289,66 +284,53 @@ static void process_free_event(struct raw_event_sample *raw,
289} 284}
290 285
291static void 286static void
292process_raw_event(event_t *raw_event __used, void *more_data, 287process_raw_event(event_t *raw_event __used, void *data,
293 int cpu, u64 timestamp, struct thread *thread) 288 int cpu, u64 timestamp, struct thread *thread)
294{ 289{
295 struct raw_event_sample *raw = more_data;
296 struct event *event; 290 struct event *event;
297 int type; 291 int type;
298 292
299 type = trace_parse_common_type(raw->data); 293 type = trace_parse_common_type(data);
300 event = trace_find_event(type); 294 event = trace_find_event(type);
301 295
302 if (!strcmp(event->name, "kmalloc") || 296 if (!strcmp(event->name, "kmalloc") ||
303 !strcmp(event->name, "kmem_cache_alloc")) { 297 !strcmp(event->name, "kmem_cache_alloc")) {
304 process_alloc_event(raw, event, cpu, timestamp, thread, 0); 298 process_alloc_event(data, event, cpu, timestamp, thread, 0);
305 return; 299 return;
306 } 300 }
307 301
308 if (!strcmp(event->name, "kmalloc_node") || 302 if (!strcmp(event->name, "kmalloc_node") ||
309 !strcmp(event->name, "kmem_cache_alloc_node")) { 303 !strcmp(event->name, "kmem_cache_alloc_node")) {
310 process_alloc_event(raw, event, cpu, timestamp, thread, 1); 304 process_alloc_event(data, event, cpu, timestamp, thread, 1);
311 return; 305 return;
312 } 306 }
313 307
314 if (!strcmp(event->name, "kfree") || 308 if (!strcmp(event->name, "kfree") ||
315 !strcmp(event->name, "kmem_cache_free")) { 309 !strcmp(event->name, "kmem_cache_free")) {
316 process_free_event(raw, event, cpu, timestamp, thread); 310 process_free_event(data, event, cpu, timestamp, thread);
317 return; 311 return;
318 } 312 }
319} 313}
320 314
321static int process_sample_event(event_t *event) 315static int process_sample_event(event_t *event)
322{ 316{
323 u64 ip = event->ip.ip; 317 struct sample_data data;
324 u64 timestamp = -1; 318 struct thread *thread;
325 u32 cpu = -1;
326 u64 period = 1;
327 void *more_data = event->ip.__more_data;
328 struct thread *thread = threads__findnew(event->ip.pid);
329 319
330 if (sample_type & PERF_SAMPLE_TIME) { 320 memset(&data, 0, sizeof(data));
331 timestamp = *(u64 *)more_data; 321 data.time = -1;
332 more_data += sizeof(u64); 322 data.cpu = -1;
333 } 323 data.period = 1;
334
335 if (sample_type & PERF_SAMPLE_CPU) {
336 cpu = *(u32 *)more_data;
337 more_data += sizeof(u32);
338 more_data += sizeof(u32); /* reserved */
339 }
340 324
341 if (sample_type & PERF_SAMPLE_PERIOD) { 325 event__parse_sample(event, sample_type, &data);
342 period = *(u64 *)more_data;
343 more_data += sizeof(u64);
344 }
345 326
346 dump_printf("(IP, %d): %d/%d: %p period: %Ld\n", 327 dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
347 event->header.misc, 328 event->header.misc,
348 event->ip.pid, event->ip.tid, 329 data.pid, data.tid,
349 (void *)(long)ip, 330 (void *)(long)data.ip,
350 (long long)period); 331 (long long)data.period);
351 332
333 thread = threads__findnew(event->ip.pid);
352 if (thread == NULL) { 334 if (thread == NULL) {
353 pr_debug("problem processing %d event, skipping it.\n", 335 pr_debug("problem processing %d event, skipping it.\n",
354 event->header.type); 336 event->header.type);
@@ -357,7 +339,8 @@ static int process_sample_event(event_t *event)
357 339
358 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 340 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
359 341
360 process_raw_event(event, more_data, cpu, timestamp, thread); 342 process_raw_event(event, data.raw_data, data.cpu,
343 data.time, thread);
361 344
362 return 0; 345 return 0;
363} 346}
@@ -543,7 +526,7 @@ static int __cmd_kmem(void)
543} 526}
544 527
545static const char * const kmem_usage[] = { 528static const char * const kmem_usage[] = {
546 "perf kmem [<options>] {record}", 529 "perf kmem [<options>] {record|stat}",
547 NULL 530 NULL
548}; 531};
549 532
@@ -703,18 +686,17 @@ static int parse_sort_opt(const struct option *opt __used,
703 return 0; 686 return 0;
704} 687}
705 688
706static int parse_stat_opt(const struct option *opt __used, 689static int parse_caller_opt(const struct option *opt __used,
707 const char *arg, int unset __used) 690 const char *arg __used, int unset __used)
708{ 691{
709 if (!arg) 692 caller_flag = (alloc_flag + 1);
710 return -1; 693 return 0;
694}
711 695
712 if (strcmp(arg, "alloc") == 0) 696static int parse_alloc_opt(const struct option *opt __used,
713 alloc_flag = (caller_flag + 1); 697 const char *arg __used, int unset __used)
714 else if (strcmp(arg, "caller") == 0) 698{
715 caller_flag = (alloc_flag + 1); 699 alloc_flag = (caller_flag + 1);
716 else
717 return -1;
718 return 0; 700 return 0;
719} 701}
720 702
@@ -739,14 +721,17 @@ static int parse_line_opt(const struct option *opt __used,
739static const struct option kmem_options[] = { 721static const struct option kmem_options[] = {
740 OPT_STRING('i', "input", &input_name, "file", 722 OPT_STRING('i', "input", &input_name, "file",
741 "input file name"), 723 "input file name"),
742 OPT_CALLBACK(0, "stat", NULL, "<alloc>|<caller>", 724 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
743 "stat selector, Pass 'alloc' or 'caller'.", 725 "show per-callsite statistics",
744 parse_stat_opt), 726 parse_caller_opt),
727 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
728 "show per-allocation statistics",
729 parse_alloc_opt),
745 OPT_CALLBACK('s', "sort", NULL, "key[,key2...]", 730 OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
746 "sort by keys: ptr, call_site, bytes, hit, pingpong, frag", 731 "sort by keys: ptr, call_site, bytes, hit, pingpong, frag",
747 parse_sort_opt), 732 parse_sort_opt),
748 OPT_CALLBACK('l', "line", NULL, "num", 733 OPT_CALLBACK('l', "line", NULL, "num",
749 "show n lins", 734 "show n lines",
750 parse_line_opt), 735 parse_line_opt),
751 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"), 736 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
752 OPT_END() 737 OPT_END()
@@ -790,18 +775,22 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __used)
790 775
791 argc = parse_options(argc, argv, kmem_options, kmem_usage, 0); 776 argc = parse_options(argc, argv, kmem_options, kmem_usage, 0);
792 777
793 if (argc && !strncmp(argv[0], "rec", 3)) 778 if (!argc)
794 return __cmd_record(argc, argv);
795 else if (argc)
796 usage_with_options(kmem_usage, kmem_options); 779 usage_with_options(kmem_usage, kmem_options);
797 780
798 if (list_empty(&caller_sort)) 781 if (!strncmp(argv[0], "rec", 3)) {
799 setup_sorting(&caller_sort, default_sort_order); 782 return __cmd_record(argc, argv);
800 if (list_empty(&alloc_sort)) 783 } else if (!strcmp(argv[0], "stat")) {
801 setup_sorting(&alloc_sort, default_sort_order); 784 setup_cpunode_map();
785
786 if (list_empty(&caller_sort))
787 setup_sorting(&caller_sort, default_sort_order);
788 if (list_empty(&alloc_sort))
789 setup_sorting(&alloc_sort, default_sort_order);
802 790
803 setup_cpunode_map(); 791 return __cmd_kmem();
792 }
804 793
805 return __cmd_kmem(); 794 return 0;
806} 795}
807 796
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index a58e11b7ea80..5a47c1e11f77 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -35,6 +35,7 @@
35#include "perf.h" 35#include "perf.h"
36#include "builtin.h" 36#include "builtin.h"
37#include "util/util.h" 37#include "util/util.h"
38#include "util/strlist.h"
38#include "util/event.h" 39#include "util/event.h"
39#include "util/debug.h" 40#include "util/debug.h"
40#include "util/parse-options.h" 41#include "util/parse-options.h"
@@ -43,11 +44,12 @@
43#include "util/probe-event.h" 44#include "util/probe-event.h"
44 45
45/* Default vmlinux search paths */ 46/* Default vmlinux search paths */
46#define NR_SEARCH_PATH 3 47#define NR_SEARCH_PATH 4
47const char *default_search_path[NR_SEARCH_PATH] = { 48const char *default_search_path[NR_SEARCH_PATH] = {
48"/lib/modules/%s/build/vmlinux", /* Custom build kernel */ 49"/lib/modules/%s/build/vmlinux", /* Custom build kernel */
49"/usr/lib/debug/lib/modules/%s/vmlinux", /* Red Hat debuginfo */ 50"/usr/lib/debug/lib/modules/%s/vmlinux", /* Red Hat debuginfo */
50"/boot/vmlinux-debug-%s", /* Ubuntu */ 51"/boot/vmlinux-debug-%s", /* Ubuntu */
52"./vmlinux", /* CWD */
51}; 53};
52 54
53#define MAX_PATH_LEN 256 55#define MAX_PATH_LEN 256
@@ -60,6 +62,7 @@ static struct {
60 int need_dwarf; 62 int need_dwarf;
61 int nr_probe; 63 int nr_probe;
62 struct probe_point probes[MAX_PROBES]; 64 struct probe_point probes[MAX_PROBES];
65 struct strlist *dellist;
63} session; 66} session;
64 67
65static bool listing; 68static bool listing;
@@ -79,6 +82,25 @@ static void parse_probe_event(const char *str)
79 pr_debug("%d arguments\n", pp->nr_args); 82 pr_debug("%d arguments\n", pp->nr_args);
80} 83}
81 84
85static void parse_probe_event_argv(int argc, const char **argv)
86{
87 int i, len;
88 char *buf;
89
90 /* Bind up rest arguments */
91 len = 0;
92 for (i = 0; i < argc; i++)
93 len += strlen(argv[i]) + 1;
94 buf = zalloc(len + 1);
95 if (!buf)
96 die("Failed to allocate memory for binding arguments.");
97 len = 0;
98 for (i = 0; i < argc; i++)
99 len += sprintf(&buf[len], "%s ", argv[i]);
100 parse_probe_event(buf);
101 free(buf);
102}
103
82static int opt_add_probe_event(const struct option *opt __used, 104static int opt_add_probe_event(const struct option *opt __used,
83 const char *str, int unset __used) 105 const char *str, int unset __used)
84{ 106{
@@ -87,6 +109,17 @@ static int opt_add_probe_event(const struct option *opt __used,
87 return 0; 109 return 0;
88} 110}
89 111
112static int opt_del_probe_event(const struct option *opt __used,
113 const char *str, int unset __used)
114{
115 if (str) {
116 if (!session.dellist)
117 session.dellist = strlist__new(true, NULL);
118 strlist__add(session.dellist, str);
119 }
120 return 0;
121}
122
90#ifndef NO_LIBDWARF 123#ifndef NO_LIBDWARF
91static int open_default_vmlinux(void) 124static int open_default_vmlinux(void)
92{ 125{
@@ -121,6 +154,7 @@ static int open_default_vmlinux(void)
121static const char * const probe_usage[] = { 154static const char * const probe_usage[] = {
122 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", 155 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
123 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 156 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
157 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
124 "perf probe --list", 158 "perf probe --list",
125 NULL 159 NULL
126}; 160};
@@ -132,7 +166,9 @@ static const struct option options[] = {
132 OPT_STRING('k', "vmlinux", &session.vmlinux, "file", 166 OPT_STRING('k', "vmlinux", &session.vmlinux, "file",
133 "vmlinux/module pathname"), 167 "vmlinux/module pathname"),
134#endif 168#endif
135 OPT_BOOLEAN('l', "list", &listing, "list up current probes"), 169 OPT_BOOLEAN('l', "list", &listing, "list up current probe events"),
170 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
171 opt_del_probe_event),
136 OPT_CALLBACK('a', "add", NULL, 172 OPT_CALLBACK('a', "add", NULL,
137#ifdef NO_LIBDWARF 173#ifdef NO_LIBDWARF
138 "FUNC[+OFFS|%return] [ARG ...]", 174 "FUNC[+OFFS|%return] [ARG ...]",
@@ -160,7 +196,7 @@ static const struct option options[] = {
160 196
161int cmd_probe(int argc, const char **argv, const char *prefix __used) 197int cmd_probe(int argc, const char **argv, const char *prefix __used)
162{ 198{
163 int i, j, ret; 199 int i, ret;
164#ifndef NO_LIBDWARF 200#ifndef NO_LIBDWARF
165 int fd; 201 int fd;
166#endif 202#endif
@@ -168,40 +204,52 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
168 204
169 argc = parse_options(argc, argv, options, probe_usage, 205 argc = parse_options(argc, argv, options, probe_usage,
170 PARSE_OPT_STOP_AT_NON_OPTION); 206 PARSE_OPT_STOP_AT_NON_OPTION);
171 for (i = 0; i < argc; i++) 207 if (argc > 0)
172 parse_probe_event(argv[i]); 208 parse_probe_event_argv(argc, argv);
173 209
174 if ((session.nr_probe == 0 && !listing) || 210 if ((session.nr_probe == 0 && !session.dellist && !listing))
175 (session.nr_probe != 0 && listing))
176 usage_with_options(probe_usage, options); 211 usage_with_options(probe_usage, options);
177 212
178 if (listing) { 213 if (listing) {
214 if (session.nr_probe != 0 || session.dellist) {
215 pr_warning(" Error: Don't use --list with"
216 " --add/--del.\n");
217 usage_with_options(probe_usage, options);
218 }
179 show_perf_probe_events(); 219 show_perf_probe_events();
180 return 0; 220 return 0;
181 } 221 }
182 222
223 if (session.dellist) {
224 del_trace_kprobe_events(session.dellist);
225 strlist__delete(session.dellist);
226 if (session.nr_probe == 0)
227 return 0;
228 }
229
183 if (session.need_dwarf) 230 if (session.need_dwarf)
184#ifdef NO_LIBDWARF 231#ifdef NO_LIBDWARF
185 die("Debuginfo-analysis is not supported"); 232 die("Debuginfo-analysis is not supported");
186#else /* !NO_LIBDWARF */ 233#else /* !NO_LIBDWARF */
187 pr_debug("Some probes require debuginfo.\n"); 234 pr_debug("Some probes require debuginfo.\n");
188 235
189 if (session.vmlinux) 236 if (session.vmlinux) {
237 pr_debug("Try to open %s.", session.vmlinux);
190 fd = open(session.vmlinux, O_RDONLY); 238 fd = open(session.vmlinux, O_RDONLY);
191 else 239 } else
192 fd = open_default_vmlinux(); 240 fd = open_default_vmlinux();
193 if (fd < 0) { 241 if (fd < 0) {
194 if (session.need_dwarf) 242 if (session.need_dwarf)
195 die("Could not open vmlinux/module file."); 243 die("Could not open debuginfo file.");
196 244
197 pr_warning("Could not open vmlinux/module file." 245 pr_debug("Could not open vmlinux/module file."
198 " Try to use symbols.\n"); 246 " Try to use symbols.\n");
199 goto end_dwarf; 247 goto end_dwarf;
200 } 248 }
201 249
202 /* Searching probe points */ 250 /* Searching probe points */
203 for (j = 0; j < session.nr_probe; j++) { 251 for (i = 0; i < session.nr_probe; i++) {
204 pp = &session.probes[j]; 252 pp = &session.probes[i];
205 if (pp->found) 253 if (pp->found)
206 continue; 254 continue;
207 255
@@ -223,8 +271,8 @@ end_dwarf:
223#endif /* !NO_LIBDWARF */ 271#endif /* !NO_LIBDWARF */
224 272
225 /* Synthesize probes without dwarf */ 273 /* Synthesize probes without dwarf */
226 for (j = 0; j < session.nr_probe; j++) { 274 for (i = 0; i < session.nr_probe; i++) {
227 pp = &session.probes[j]; 275 pp = &session.probes[i];
228 if (pp->found) /* This probe is already found. */ 276 if (pp->found) /* This probe is already found. */
229 continue; 277 continue;
230 278
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 383c4ab4f9af..2b9eb3a553ed 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -605,44 +605,41 @@ static int validate_chain(struct ip_callchain *chain, event_t *event)
605 605
606static int process_sample_event(event_t *event) 606static int process_sample_event(event_t *event)
607{ 607{
608 u64 ip = event->ip.ip; 608 struct sample_data data;
609 u64 period = 1;
610 void *more_data = event->ip.__more_data;
611 struct ip_callchain *chain = NULL;
612 int cpumode; 609 int cpumode;
613 struct addr_location al; 610 struct addr_location al;
614 struct thread *thread = threads__findnew(event->ip.pid); 611 struct thread *thread;
615 612
616 if (sample_type & PERF_SAMPLE_PERIOD) { 613 memset(&data, 0, sizeof(data));
617 period = *(u64 *)more_data; 614 data.period = 1;
618 more_data += sizeof(u64); 615
619 } 616 event__parse_sample(event, sample_type, &data);
620 617
621 dump_printf("(IP, %d): %d/%d: %p period: %Ld\n", 618 dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
622 event->header.misc, 619 event->header.misc,
623 event->ip.pid, event->ip.tid, 620 data.pid, data.tid,
624 (void *)(long)ip, 621 (void *)(long)data.ip,
625 (long long)period); 622 (long long)data.period);
626 623
627 if (sample_type & PERF_SAMPLE_CALLCHAIN) { 624 if (sample_type & PERF_SAMPLE_CALLCHAIN) {
628 unsigned int i; 625 unsigned int i;
629 626
630 chain = (void *)more_data; 627 dump_printf("... chain: nr:%Lu\n", data.callchain->nr);
631
632 dump_printf("... chain: nr:%Lu\n", chain->nr);
633 628
634 if (validate_chain(chain, event) < 0) { 629 if (validate_chain(data.callchain, event) < 0) {
635 pr_debug("call-chain problem with event, " 630 pr_debug("call-chain problem with event, "
636 "skipping it.\n"); 631 "skipping it.\n");
637 return 0; 632 return 0;
638 } 633 }
639 634
640 if (dump_trace) { 635 if (dump_trace) {
641 for (i = 0; i < chain->nr; i++) 636 for (i = 0; i < data.callchain->nr; i++)
642 dump_printf("..... %2d: %016Lx\n", i, chain->ips[i]); 637 dump_printf("..... %2d: %016Lx\n",
638 i, data.callchain->ips[i]);
643 } 639 }
644 } 640 }
645 641
642 thread = threads__findnew(data.pid);
646 if (thread == NULL) { 643 if (thread == NULL) {
647 pr_debug("problem processing %d event, skipping it.\n", 644 pr_debug("problem processing %d event, skipping it.\n",
648 event->header.type); 645 event->header.type);
@@ -657,7 +654,7 @@ static int process_sample_event(event_t *event)
657 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 654 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
658 655
659 thread__find_addr_location(thread, cpumode, 656 thread__find_addr_location(thread, cpumode,
660 MAP__FUNCTION, ip, &al, NULL); 657 MAP__FUNCTION, data.ip, &al, NULL);
661 /* 658 /*
662 * We have to do this here as we may have a dso with no symbol hit that 659 * We have to do this here as we may have a dso with no symbol hit that
663 * has a name longer than the ones with symbols sampled. 660 * has a name longer than the ones with symbols sampled.
@@ -675,12 +672,12 @@ static int process_sample_event(event_t *event)
675 if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name)) 672 if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name))
676 return 0; 673 return 0;
677 674
678 if (hist_entry__add(&al, chain, period)) { 675 if (hist_entry__add(&al, data.callchain, data.period)) {
679 pr_debug("problem incrementing symbol count, skipping event\n"); 676 pr_debug("problem incrementing symbol count, skipping event\n");
680 return -1; 677 return -1;
681 } 678 }
682 679
683 event__stats.total += period; 680 event__stats.total += data.period;
684 681
685 return 0; 682 return 0;
686} 683}
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 26b782f26ee1..7cca7c15b40a 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -13,7 +13,6 @@
13#include "util/debug.h" 13#include "util/debug.h"
14#include "util/data_map.h" 14#include "util/data_map.h"
15 15
16#include <sys/types.h>
17#include <sys/prctl.h> 16#include <sys/prctl.h>
18 17
19#include <semaphore.h> 18#include <semaphore.h>
@@ -141,6 +140,7 @@ struct work_atoms {
141 struct thread *thread; 140 struct thread *thread;
142 struct rb_node node; 141 struct rb_node node;
143 u64 max_lat; 142 u64 max_lat;
143 u64 max_lat_at;
144 u64 total_lat; 144 u64 total_lat;
145 u64 nb_atoms; 145 u64 nb_atoms;
146 u64 total_runtime; 146 u64 total_runtime;
@@ -414,34 +414,33 @@ static u64 get_cpu_usage_nsec_parent(void)
414 return sum; 414 return sum;
415} 415}
416 416
417static u64 get_cpu_usage_nsec_self(void) 417static int self_open_counters(void)
418{ 418{
419 char filename [] = "/proc/1234567890/sched"; 419 struct perf_event_attr attr;
420 unsigned long msecs, nsecs; 420 int fd;
421 char *line = NULL;
422 u64 total = 0;
423 size_t len = 0;
424 ssize_t chars;
425 FILE *file;
426 int ret;
427 421
428 sprintf(filename, "/proc/%d/sched", getpid()); 422 memset(&attr, 0, sizeof(attr));
429 file = fopen(filename, "r");
430 BUG_ON(!file);
431 423
432 while ((chars = getline(&line, &len, file)) != -1) { 424 attr.type = PERF_TYPE_SOFTWARE;
433 ret = sscanf(line, "se.sum_exec_runtime : %ld.%06ld\n", 425 attr.config = PERF_COUNT_SW_TASK_CLOCK;
434 &msecs, &nsecs); 426
435 if (ret == 2) { 427 fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
436 total = msecs*1e6 + nsecs;
437 break;
438 }
439 }
440 if (line)
441 free(line);
442 fclose(file);
443 428
444 return total; 429 if (fd < 0)
430 die("Error: sys_perf_event_open() syscall returned"
431 "with %d (%s)\n", fd, strerror(errno));
432 return fd;
433}
434
435static u64 get_cpu_usage_nsec_self(int fd)
436{
437 u64 runtime;
438 int ret;
439
440 ret = read(fd, &runtime, sizeof(runtime));
441 BUG_ON(ret != sizeof(runtime));
442
443 return runtime;
445} 444}
446 445
447static void *thread_func(void *ctx) 446static void *thread_func(void *ctx)
@@ -450,9 +449,11 @@ static void *thread_func(void *ctx)
450 u64 cpu_usage_0, cpu_usage_1; 449 u64 cpu_usage_0, cpu_usage_1;
451 unsigned long i, ret; 450 unsigned long i, ret;
452 char comm2[22]; 451 char comm2[22];
452 int fd;
453 453
454 sprintf(comm2, ":%s", this_task->comm); 454 sprintf(comm2, ":%s", this_task->comm);
455 prctl(PR_SET_NAME, comm2); 455 prctl(PR_SET_NAME, comm2);
456 fd = self_open_counters();
456 457
457again: 458again:
458 ret = sem_post(&this_task->ready_for_work); 459 ret = sem_post(&this_task->ready_for_work);
@@ -462,16 +463,15 @@ again:
462 ret = pthread_mutex_unlock(&start_work_mutex); 463 ret = pthread_mutex_unlock(&start_work_mutex);
463 BUG_ON(ret); 464 BUG_ON(ret);
464 465
465 cpu_usage_0 = get_cpu_usage_nsec_self(); 466 cpu_usage_0 = get_cpu_usage_nsec_self(fd);
466 467
467 for (i = 0; i < this_task->nr_events; i++) { 468 for (i = 0; i < this_task->nr_events; i++) {
468 this_task->curr_event = i; 469 this_task->curr_event = i;
469 process_sched_event(this_task, this_task->atoms[i]); 470 process_sched_event(this_task, this_task->atoms[i]);
470 } 471 }
471 472
472 cpu_usage_1 = get_cpu_usage_nsec_self(); 473 cpu_usage_1 = get_cpu_usage_nsec_self(fd);
473 this_task->cpu_usage = cpu_usage_1 - cpu_usage_0; 474 this_task->cpu_usage = cpu_usage_1 - cpu_usage_0;
474
475 ret = sem_post(&this_task->work_done_sem); 475 ret = sem_post(&this_task->work_done_sem);
476 BUG_ON(ret); 476 BUG_ON(ret);
477 477
@@ -628,11 +628,6 @@ static void test_calibrations(void)
628 printf("the sleep test took %Ld nsecs\n", T1-T0); 628 printf("the sleep test took %Ld nsecs\n", T1-T0);
629} 629}
630 630
631struct raw_event_sample {
632 u32 size;
633 char data[0];
634};
635
636#define FILL_FIELD(ptr, field, event, data) \ 631#define FILL_FIELD(ptr, field, event, data) \
637 ptr.field = (typeof(ptr.field)) raw_field_value(event, #field, data) 632 ptr.field = (typeof(ptr.field)) raw_field_value(event, #field, data)
638 633
@@ -1019,8 +1014,10 @@ add_sched_in_event(struct work_atoms *atoms, u64 timestamp)
1019 1014
1020 delta = atom->sched_in_time - atom->wake_up_time; 1015 delta = atom->sched_in_time - atom->wake_up_time;
1021 atoms->total_lat += delta; 1016 atoms->total_lat += delta;
1022 if (delta > atoms->max_lat) 1017 if (delta > atoms->max_lat) {
1023 atoms->max_lat = delta; 1018 atoms->max_lat = delta;
1019 atoms->max_lat_at = timestamp;
1020 }
1024 atoms->nb_atoms++; 1021 atoms->nb_atoms++;
1025} 1022}
1026 1023
@@ -1216,10 +1213,11 @@ static void output_lat_thread(struct work_atoms *work_list)
1216 1213
1217 avg = work_list->total_lat / work_list->nb_atoms; 1214 avg = work_list->total_lat / work_list->nb_atoms;
1218 1215
1219 printf("|%11.3f ms |%9llu | avg:%9.3f ms | max:%9.3f ms |\n", 1216 printf("|%11.3f ms |%9llu | avg:%9.3f ms | max:%9.3f ms | max at: %9.6f s\n",
1220 (double)work_list->total_runtime / 1e6, 1217 (double)work_list->total_runtime / 1e6,
1221 work_list->nb_atoms, (double)avg / 1e6, 1218 work_list->nb_atoms, (double)avg / 1e6,
1222 (double)work_list->max_lat / 1e6); 1219 (double)work_list->max_lat / 1e6,
1220 (double)work_list->max_lat_at / 1e9);
1223} 1221}
1224 1222
1225static int pid_cmp(struct work_atoms *l, struct work_atoms *r) 1223static int pid_cmp(struct work_atoms *l, struct work_atoms *r)
@@ -1356,7 +1354,7 @@ static void sort_lat(void)
1356static struct trace_sched_handler *trace_handler; 1354static struct trace_sched_handler *trace_handler;
1357 1355
1358static void 1356static void
1359process_sched_wakeup_event(struct raw_event_sample *raw, 1357process_sched_wakeup_event(void *data,
1360 struct event *event, 1358 struct event *event,
1361 int cpu __used, 1359 int cpu __used,
1362 u64 timestamp __used, 1360 u64 timestamp __used,
@@ -1364,13 +1362,13 @@ process_sched_wakeup_event(struct raw_event_sample *raw,
1364{ 1362{
1365 struct trace_wakeup_event wakeup_event; 1363 struct trace_wakeup_event wakeup_event;
1366 1364
1367 FILL_COMMON_FIELDS(wakeup_event, event, raw->data); 1365 FILL_COMMON_FIELDS(wakeup_event, event, data);
1368 1366
1369 FILL_ARRAY(wakeup_event, comm, event, raw->data); 1367 FILL_ARRAY(wakeup_event, comm, event, data);
1370 FILL_FIELD(wakeup_event, pid, event, raw->data); 1368 FILL_FIELD(wakeup_event, pid, event, data);
1371 FILL_FIELD(wakeup_event, prio, event, raw->data); 1369 FILL_FIELD(wakeup_event, prio, event, data);
1372 FILL_FIELD(wakeup_event, success, event, raw->data); 1370 FILL_FIELD(wakeup_event, success, event, data);
1373 FILL_FIELD(wakeup_event, cpu, event, raw->data); 1371 FILL_FIELD(wakeup_event, cpu, event, data);
1374 1372
1375 if (trace_handler->wakeup_event) 1373 if (trace_handler->wakeup_event)
1376 trace_handler->wakeup_event(&wakeup_event, event, cpu, timestamp, thread); 1374 trace_handler->wakeup_event(&wakeup_event, event, cpu, timestamp, thread);
@@ -1469,7 +1467,7 @@ map_switch_event(struct trace_switch_event *switch_event,
1469 1467
1470 1468
1471static void 1469static void
1472process_sched_switch_event(struct raw_event_sample *raw, 1470process_sched_switch_event(void *data,
1473 struct event *event, 1471 struct event *event,
1474 int this_cpu, 1472 int this_cpu,
1475 u64 timestamp __used, 1473 u64 timestamp __used,
@@ -1477,15 +1475,15 @@ process_sched_switch_event(struct raw_event_sample *raw,
1477{ 1475{
1478 struct trace_switch_event switch_event; 1476 struct trace_switch_event switch_event;
1479 1477
1480 FILL_COMMON_FIELDS(switch_event, event, raw->data); 1478 FILL_COMMON_FIELDS(switch_event, event, data);
1481 1479
1482 FILL_ARRAY(switch_event, prev_comm, event, raw->data); 1480 FILL_ARRAY(switch_event, prev_comm, event, data);
1483 FILL_FIELD(switch_event, prev_pid, event, raw->data); 1481 FILL_FIELD(switch_event, prev_pid, event, data);
1484 FILL_FIELD(switch_event, prev_prio, event, raw->data); 1482 FILL_FIELD(switch_event, prev_prio, event, data);
1485 FILL_FIELD(switch_event, prev_state, event, raw->data); 1483 FILL_FIELD(switch_event, prev_state, event, data);
1486 FILL_ARRAY(switch_event, next_comm, event, raw->data); 1484 FILL_ARRAY(switch_event, next_comm, event, data);
1487 FILL_FIELD(switch_event, next_pid, event, raw->data); 1485 FILL_FIELD(switch_event, next_pid, event, data);
1488 FILL_FIELD(switch_event, next_prio, event, raw->data); 1486 FILL_FIELD(switch_event, next_prio, event, data);
1489 1487
1490 if (curr_pid[this_cpu] != (u32)-1) { 1488 if (curr_pid[this_cpu] != (u32)-1) {
1491 /* 1489 /*
@@ -1502,7 +1500,7 @@ process_sched_switch_event(struct raw_event_sample *raw,
1502} 1500}
1503 1501
1504static void 1502static void
1505process_sched_runtime_event(struct raw_event_sample *raw, 1503process_sched_runtime_event(void *data,
1506 struct event *event, 1504 struct event *event,
1507 int cpu __used, 1505 int cpu __used,
1508 u64 timestamp __used, 1506 u64 timestamp __used,
@@ -1510,17 +1508,17 @@ process_sched_runtime_event(struct raw_event_sample *raw,
1510{ 1508{
1511 struct trace_runtime_event runtime_event; 1509 struct trace_runtime_event runtime_event;
1512 1510
1513 FILL_ARRAY(runtime_event, comm, event, raw->data); 1511 FILL_ARRAY(runtime_event, comm, event, data);
1514 FILL_FIELD(runtime_event, pid, event, raw->data); 1512 FILL_FIELD(runtime_event, pid, event, data);
1515 FILL_FIELD(runtime_event, runtime, event, raw->data); 1513 FILL_FIELD(runtime_event, runtime, event, data);
1516 FILL_FIELD(runtime_event, vruntime, event, raw->data); 1514 FILL_FIELD(runtime_event, vruntime, event, data);
1517 1515
1518 if (trace_handler->runtime_event) 1516 if (trace_handler->runtime_event)
1519 trace_handler->runtime_event(&runtime_event, event, cpu, timestamp, thread); 1517 trace_handler->runtime_event(&runtime_event, event, cpu, timestamp, thread);
1520} 1518}
1521 1519
1522static void 1520static void
1523process_sched_fork_event(struct raw_event_sample *raw, 1521process_sched_fork_event(void *data,
1524 struct event *event, 1522 struct event *event,
1525 int cpu __used, 1523 int cpu __used,
1526 u64 timestamp __used, 1524 u64 timestamp __used,
@@ -1528,12 +1526,12 @@ process_sched_fork_event(struct raw_event_sample *raw,
1528{ 1526{
1529 struct trace_fork_event fork_event; 1527 struct trace_fork_event fork_event;
1530 1528
1531 FILL_COMMON_FIELDS(fork_event, event, raw->data); 1529 FILL_COMMON_FIELDS(fork_event, event, data);
1532 1530
1533 FILL_ARRAY(fork_event, parent_comm, event, raw->data); 1531 FILL_ARRAY(fork_event, parent_comm, event, data);
1534 FILL_FIELD(fork_event, parent_pid, event, raw->data); 1532 FILL_FIELD(fork_event, parent_pid, event, data);
1535 FILL_ARRAY(fork_event, child_comm, event, raw->data); 1533 FILL_ARRAY(fork_event, child_comm, event, data);
1536 FILL_FIELD(fork_event, child_pid, event, raw->data); 1534 FILL_FIELD(fork_event, child_pid, event, data);
1537 1535
1538 if (trace_handler->fork_event) 1536 if (trace_handler->fork_event)
1539 trace_handler->fork_event(&fork_event, event, cpu, timestamp, thread); 1537 trace_handler->fork_event(&fork_event, event, cpu, timestamp, thread);
@@ -1550,7 +1548,7 @@ process_sched_exit_event(struct event *event,
1550} 1548}
1551 1549
1552static void 1550static void
1553process_sched_migrate_task_event(struct raw_event_sample *raw, 1551process_sched_migrate_task_event(void *data,
1554 struct event *event, 1552 struct event *event,
1555 int cpu __used, 1553 int cpu __used,
1556 u64 timestamp __used, 1554 u64 timestamp __used,
@@ -1558,80 +1556,66 @@ process_sched_migrate_task_event(struct raw_event_sample *raw,
1558{ 1556{
1559 struct trace_migrate_task_event migrate_task_event; 1557 struct trace_migrate_task_event migrate_task_event;
1560 1558
1561 FILL_COMMON_FIELDS(migrate_task_event, event, raw->data); 1559 FILL_COMMON_FIELDS(migrate_task_event, event, data);
1562 1560
1563 FILL_ARRAY(migrate_task_event, comm, event, raw->data); 1561 FILL_ARRAY(migrate_task_event, comm, event, data);
1564 FILL_FIELD(migrate_task_event, pid, event, raw->data); 1562 FILL_FIELD(migrate_task_event, pid, event, data);
1565 FILL_FIELD(migrate_task_event, prio, event, raw->data); 1563 FILL_FIELD(migrate_task_event, prio, event, data);
1566 FILL_FIELD(migrate_task_event, cpu, event, raw->data); 1564 FILL_FIELD(migrate_task_event, cpu, event, data);
1567 1565
1568 if (trace_handler->migrate_task_event) 1566 if (trace_handler->migrate_task_event)
1569 trace_handler->migrate_task_event(&migrate_task_event, event, cpu, timestamp, thread); 1567 trace_handler->migrate_task_event(&migrate_task_event, event, cpu, timestamp, thread);
1570} 1568}
1571 1569
1572static void 1570static void
1573process_raw_event(event_t *raw_event __used, void *more_data, 1571process_raw_event(event_t *raw_event __used, void *data,
1574 int cpu, u64 timestamp, struct thread *thread) 1572 int cpu, u64 timestamp, struct thread *thread)
1575{ 1573{
1576 struct raw_event_sample *raw = more_data;
1577 struct event *event; 1574 struct event *event;
1578 int type; 1575 int type;
1579 1576
1580 type = trace_parse_common_type(raw->data); 1577
1578 type = trace_parse_common_type(data);
1581 event = trace_find_event(type); 1579 event = trace_find_event(type);
1582 1580
1583 if (!strcmp(event->name, "sched_switch")) 1581 if (!strcmp(event->name, "sched_switch"))
1584 process_sched_switch_event(raw, event, cpu, timestamp, thread); 1582 process_sched_switch_event(data, event, cpu, timestamp, thread);
1585 if (!strcmp(event->name, "sched_stat_runtime")) 1583 if (!strcmp(event->name, "sched_stat_runtime"))
1586 process_sched_runtime_event(raw, event, cpu, timestamp, thread); 1584 process_sched_runtime_event(data, event, cpu, timestamp, thread);
1587 if (!strcmp(event->name, "sched_wakeup")) 1585 if (!strcmp(event->name, "sched_wakeup"))
1588 process_sched_wakeup_event(raw, event, cpu, timestamp, thread); 1586 process_sched_wakeup_event(data, event, cpu, timestamp, thread);
1589 if (!strcmp(event->name, "sched_wakeup_new")) 1587 if (!strcmp(event->name, "sched_wakeup_new"))
1590 process_sched_wakeup_event(raw, event, cpu, timestamp, thread); 1588 process_sched_wakeup_event(data, event, cpu, timestamp, thread);
1591 if (!strcmp(event->name, "sched_process_fork")) 1589 if (!strcmp(event->name, "sched_process_fork"))
1592 process_sched_fork_event(raw, event, cpu, timestamp, thread); 1590 process_sched_fork_event(data, event, cpu, timestamp, thread);
1593 if (!strcmp(event->name, "sched_process_exit")) 1591 if (!strcmp(event->name, "sched_process_exit"))
1594 process_sched_exit_event(event, cpu, timestamp, thread); 1592 process_sched_exit_event(event, cpu, timestamp, thread);
1595 if (!strcmp(event->name, "sched_migrate_task")) 1593 if (!strcmp(event->name, "sched_migrate_task"))
1596 process_sched_migrate_task_event(raw, event, cpu, timestamp, thread); 1594 process_sched_migrate_task_event(data, event, cpu, timestamp, thread);
1597} 1595}
1598 1596
1599static int process_sample_event(event_t *event) 1597static int process_sample_event(event_t *event)
1600{ 1598{
1599 struct sample_data data;
1601 struct thread *thread; 1600 struct thread *thread;
1602 u64 ip = event->ip.ip;
1603 u64 timestamp = -1;
1604 u32 cpu = -1;
1605 u64 period = 1;
1606 void *more_data = event->ip.__more_data;
1607 1601
1608 if (!(sample_type & PERF_SAMPLE_RAW)) 1602 if (!(sample_type & PERF_SAMPLE_RAW))
1609 return 0; 1603 return 0;
1610 1604
1611 thread = threads__findnew(event->ip.pid); 1605 memset(&data, 0, sizeof(data));
1606 data.time = -1;
1607 data.cpu = -1;
1608 data.period = -1;
1612 1609
1613 if (sample_type & PERF_SAMPLE_TIME) { 1610 event__parse_sample(event, sample_type, &data);
1614 timestamp = *(u64 *)more_data;
1615 more_data += sizeof(u64);
1616 }
1617
1618 if (sample_type & PERF_SAMPLE_CPU) {
1619 cpu = *(u32 *)more_data;
1620 more_data += sizeof(u32);
1621 more_data += sizeof(u32); /* reserved */
1622 }
1623
1624 if (sample_type & PERF_SAMPLE_PERIOD) {
1625 period = *(u64 *)more_data;
1626 more_data += sizeof(u64);
1627 }
1628 1611
1629 dump_printf("(IP, %d): %d/%d: %p period: %Ld\n", 1612 dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
1630 event->header.misc, 1613 event->header.misc,
1631 event->ip.pid, event->ip.tid, 1614 data.pid, data.tid,
1632 (void *)(long)ip, 1615 (void *)(long)data.ip,
1633 (long long)period); 1616 (long long)data.period);
1634 1617
1618 thread = threads__findnew(data.pid);
1635 if (thread == NULL) { 1619 if (thread == NULL) {
1636 pr_debug("problem processing %d event, skipping it.\n", 1620 pr_debug("problem processing %d event, skipping it.\n",
1637 event->header.type); 1621 event->header.type);
@@ -1640,10 +1624,10 @@ static int process_sample_event(event_t *event)
1640 1624
1641 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 1625 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
1642 1626
1643 if (profile_cpu != -1 && profile_cpu != (int) cpu) 1627 if (profile_cpu != -1 && profile_cpu != (int)data.cpu)
1644 return 0; 1628 return 0;
1645 1629
1646 process_raw_event(event, more_data, cpu, timestamp, thread); 1630 process_raw_event(event, data.raw_data, data.cpu, data.time, thread);
1647 1631
1648 return 0; 1632 return 0;
1649} 1633}
@@ -1724,9 +1708,9 @@ static void __cmd_lat(void)
1724 read_events(); 1708 read_events();
1725 sort_lat(); 1709 sort_lat();
1726 1710
1727 printf("\n -----------------------------------------------------------------------------------------\n"); 1711 printf("\n ---------------------------------------------------------------------------------------------------------------\n");
1728 printf(" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms |\n"); 1712 printf(" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms | Maximum delay at |\n");
1729 printf(" -----------------------------------------------------------------------------------------\n"); 1713 printf(" ---------------------------------------------------------------------------------------------------------------\n");
1730 1714
1731 next = rb_first(&sorted_atom_root); 1715 next = rb_first(&sorted_atom_root);
1732 1716
@@ -1902,13 +1886,18 @@ static int __cmd_record(int argc, const char **argv)
1902 1886
1903int cmd_sched(int argc, const char **argv, const char *prefix __used) 1887int cmd_sched(int argc, const char **argv, const char *prefix __used)
1904{ 1888{
1905 symbol__init(0);
1906
1907 argc = parse_options(argc, argv, sched_options, sched_usage, 1889 argc = parse_options(argc, argv, sched_options, sched_usage,
1908 PARSE_OPT_STOP_AT_NON_OPTION); 1890 PARSE_OPT_STOP_AT_NON_OPTION);
1909 if (!argc) 1891 if (!argc)
1910 usage_with_options(sched_usage, sched_options); 1892 usage_with_options(sched_usage, sched_options);
1911 1893
1894 /*
1895 * Aliased to 'perf trace' for now:
1896 */
1897 if (!strcmp(argv[0], "trace"))
1898 return cmd_trace(argc, argv, prefix);
1899
1900 symbol__init(0);
1912 if (!strncmp(argv[0], "rec", 3)) { 1901 if (!strncmp(argv[0], "rec", 3)) {
1913 return __cmd_record(argc, argv); 1902 return __cmd_record(argc, argv);
1914 } else if (!strncmp(argv[0], "lat", 3)) { 1903 } else if (!strncmp(argv[0], "lat", 3)) {
@@ -1932,11 +1921,6 @@ int cmd_sched(int argc, const char **argv, const char *prefix __used)
1932 usage_with_options(replay_usage, replay_options); 1921 usage_with_options(replay_usage, replay_options);
1933 } 1922 }
1934 __cmd_replay(); 1923 __cmd_replay();
1935 } else if (!strcmp(argv[0], "trace")) {
1936 /*
1937 * Aliased to 'perf trace' for now:
1938 */
1939 return cmd_trace(argc, argv, prefix);
1940 } else { 1924 } else {
1941 usage_with_options(sched_usage, sched_options); 1925 usage_with_options(sched_usage, sched_options);
1942 } 1926 }
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index cb58b6605fcc..f472df9561ee 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -302,12 +302,11 @@ process_exit_event(event_t *event)
302} 302}
303 303
304struct trace_entry { 304struct trace_entry {
305 u32 size;
306 unsigned short type; 305 unsigned short type;
307 unsigned char flags; 306 unsigned char flags;
308 unsigned char preempt_count; 307 unsigned char preempt_count;
309 int pid; 308 int pid;
310 int tgid; 309 int lock_depth;
311}; 310};
312 311
313struct power_entry { 312struct power_entry {
@@ -484,43 +483,22 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
484static int 483static int
485process_sample_event(event_t *event) 484process_sample_event(event_t *event)
486{ 485{
487 int cursor = 0; 486 struct sample_data data;
488 u64 addr = 0;
489 u64 stamp = 0;
490 u32 cpu = 0;
491 u32 pid = 0;
492 struct trace_entry *te; 487 struct trace_entry *te;
493 488
494 if (sample_type & PERF_SAMPLE_IP) 489 memset(&data, 0, sizeof(data));
495 cursor++;
496
497 if (sample_type & PERF_SAMPLE_TID) {
498 pid = event->sample.array[cursor]>>32;
499 cursor++;
500 }
501 if (sample_type & PERF_SAMPLE_TIME) {
502 stamp = event->sample.array[cursor++];
503 490
504 if (!first_time || first_time > stamp) 491 event__parse_sample(event, sample_type, &data);
505 first_time = stamp;
506 if (last_time < stamp)
507 last_time = stamp;
508 492
493 if (sample_type & PERF_SAMPLE_TIME) {
494 if (!first_time || first_time > data.time)
495 first_time = data.time;
496 if (last_time < data.time)
497 last_time = data.time;
509 } 498 }
510 if (sample_type & PERF_SAMPLE_ADDR)
511 addr = event->sample.array[cursor++];
512 if (sample_type & PERF_SAMPLE_ID)
513 cursor++;
514 if (sample_type & PERF_SAMPLE_STREAM_ID)
515 cursor++;
516 if (sample_type & PERF_SAMPLE_CPU)
517 cpu = event->sample.array[cursor++] & 0xFFFFFFFF;
518 if (sample_type & PERF_SAMPLE_PERIOD)
519 cursor++;
520
521 te = (void *)&event->sample.array[cursor];
522 499
523 if (sample_type & PERF_SAMPLE_RAW && te->size > 0) { 500 te = (void *)data.raw_data;
501 if (sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) {
524 char *event_str; 502 char *event_str;
525 struct power_entry *pe; 503 struct power_entry *pe;
526 504
@@ -532,19 +510,19 @@ process_sample_event(event_t *event)
532 return 0; 510 return 0;
533 511
534 if (strcmp(event_str, "power:power_start") == 0) 512 if (strcmp(event_str, "power:power_start") == 0)
535 c_state_start(cpu, stamp, pe->value); 513 c_state_start(data.cpu, data.time, pe->value);
536 514
537 if (strcmp(event_str, "power:power_end") == 0) 515 if (strcmp(event_str, "power:power_end") == 0)
538 c_state_end(cpu, stamp); 516 c_state_end(data.cpu, data.time);
539 517
540 if (strcmp(event_str, "power:power_frequency") == 0) 518 if (strcmp(event_str, "power:power_frequency") == 0)
541 p_state_change(cpu, stamp, pe->value); 519 p_state_change(data.cpu, data.time, pe->value);
542 520
543 if (strcmp(event_str, "sched:sched_wakeup") == 0) 521 if (strcmp(event_str, "sched:sched_wakeup") == 0)
544 sched_wakeup(cpu, stamp, pid, te); 522 sched_wakeup(data.cpu, data.time, data.pid, te);
545 523
546 if (strcmp(event_str, "sched:sched_switch") == 0) 524 if (strcmp(event_str, "sched:sched_switch") == 0)
547 sched_switch(cpu, stamp, te); 525 sched_switch(data.cpu, data.time, te);
548 } 526 }
549 return 0; 527 return 0;
550} 528}
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index abb914aa7be6..c2fcc34486f5 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -66,58 +66,40 @@ static u64 sample_type;
66 66
67static int process_sample_event(event_t *event) 67static int process_sample_event(event_t *event)
68{ 68{
69 u64 ip = event->ip.ip; 69 struct sample_data data;
70 u64 timestamp = -1; 70 struct thread *thread;
71 u32 cpu = -1;
72 u64 period = 1;
73 void *more_data = event->ip.__more_data;
74 struct thread *thread = threads__findnew(event->ip.pid);
75
76 if (sample_type & PERF_SAMPLE_TIME) {
77 timestamp = *(u64 *)more_data;
78 more_data += sizeof(u64);
79 }
80 71
81 if (sample_type & PERF_SAMPLE_CPU) { 72 memset(&data, 0, sizeof(data));
82 cpu = *(u32 *)more_data; 73 data.time = -1;
83 more_data += sizeof(u32); 74 data.cpu = -1;
84 more_data += sizeof(u32); /* reserved */ 75 data.period = 1;
85 }
86 76
87 if (sample_type & PERF_SAMPLE_PERIOD) { 77 event__parse_sample(event, sample_type, &data);
88 period = *(u64 *)more_data;
89 more_data += sizeof(u64);
90 }
91 78
92 dump_printf("(IP, %d): %d/%d: %p period: %Ld\n", 79 dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
93 event->header.misc, 80 event->header.misc,
94 event->ip.pid, event->ip.tid, 81 data.pid, data.tid,
95 (void *)(long)ip, 82 (void *)(long)data.ip,
96 (long long)period); 83 (long long)data.period);
97 84
85 thread = threads__findnew(event->ip.pid);
98 if (thread == NULL) { 86 if (thread == NULL) {
99 pr_debug("problem processing %d event, skipping it.\n", 87 pr_debug("problem processing %d event, skipping it.\n",
100 event->header.type); 88 event->header.type);
101 return -1; 89 return -1;
102 } 90 }
103 91
104 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
105
106 if (sample_type & PERF_SAMPLE_RAW) { 92 if (sample_type & PERF_SAMPLE_RAW) {
107 struct {
108 u32 size;
109 char data[0];
110 } *raw = more_data;
111
112 /* 93 /*
113 * FIXME: better resolve from pid from the struct trace_entry 94 * FIXME: better resolve from pid from the struct trace_entry
114 * field, although it should be the same than this perf 95 * field, although it should be the same than this perf
115 * event pid 96 * event pid
116 */ 97 */
117 scripting_ops->process_event(cpu, raw->data, raw->size, 98 scripting_ops->process_event(data.cpu, data.raw_data,
118 timestamp, thread->comm); 99 data.raw_size,
100 data.time, thread->comm);
119 } 101 }
120 event__stats.total += period; 102 event__stats.total += data.period;
121 103
122 return 0; 104 return 0;
123} 105}
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
index ca0bedf637c2..59b65d0bd7c1 100644
--- a/tools/perf/util/data_map.c
+++ b/tools/perf/util/data_map.c
@@ -100,11 +100,11 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
100 } 100 }
101} 101}
102 102
103int perf_header__read_build_ids(int input, off_t offset, off_t size) 103int perf_header__read_build_ids(int input, u64 offset, u64 size)
104{ 104{
105 struct build_id_event bev; 105 struct build_id_event bev;
106 char filename[PATH_MAX]; 106 char filename[PATH_MAX];
107 off_t limit = offset + size; 107 u64 limit = offset + size;
108 int err = -1; 108 int err = -1;
109 109
110 while (offset < limit) { 110 while (offset < limit) {
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h
index 3180ff7e3633..258a87bcc4fb 100644
--- a/tools/perf/util/data_map.h
+++ b/tools/perf/util/data_map.h
@@ -27,6 +27,6 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
27 int full_paths, 27 int full_paths,
28 int *cwdlen, 28 int *cwdlen,
29 char **cwd); 29 char **cwd);
30int perf_header__read_build_ids(int input, off_t offset, off_t file_size); 30int perf_header__read_build_ids(int input, u64 offset, u64 file_size);
31 31
32#endif 32#endif
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 414b89d1bde9..4dcecafa85dc 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -310,3 +310,70 @@ int event__preprocess_sample(const event_t *self, struct addr_location *al,
310 al->level == 'H' ? "[hypervisor]" : "<not found>"); 310 al->level == 'H' ? "[hypervisor]" : "<not found>");
311 return 0; 311 return 0;
312} 312}
313
314int event__parse_sample(event_t *event, u64 type, struct sample_data *data)
315{
316 u64 *array = event->sample.array;
317
318 if (type & PERF_SAMPLE_IP) {
319 data->ip = event->ip.ip;
320 array++;
321 }
322
323 if (type & PERF_SAMPLE_TID) {
324 u32 *p = (u32 *)array;
325 data->pid = p[0];
326 data->tid = p[1];
327 array++;
328 }
329
330 if (type & PERF_SAMPLE_TIME) {
331 data->time = *array;
332 array++;
333 }
334
335 if (type & PERF_SAMPLE_ADDR) {
336 data->addr = *array;
337 array++;
338 }
339
340 if (type & PERF_SAMPLE_ID) {
341 data->id = *array;
342 array++;
343 }
344
345 if (type & PERF_SAMPLE_STREAM_ID) {
346 data->stream_id = *array;
347 array++;
348 }
349
350 if (type & PERF_SAMPLE_CPU) {
351 u32 *p = (u32 *)array;
352 data->cpu = *p;
353 array++;
354 }
355
356 if (type & PERF_SAMPLE_PERIOD) {
357 data->period = *array;
358 array++;
359 }
360
361 if (type & PERF_SAMPLE_READ) {
362 pr_debug("PERF_SAMPLE_READ is unsuported for now\n");
363 return -1;
364 }
365
366 if (type & PERF_SAMPLE_CALLCHAIN) {
367 data->callchain = (struct ip_callchain *)array;
368 array += 1 + data->callchain->nr;
369 }
370
371 if (type & PERF_SAMPLE_RAW) {
372 u32 *p = (u32 *)array;
373 data->raw_size = *p;
374 p++;
375 data->raw_data = p;
376 }
377
378 return 0;
379}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index a4cc8105cf67..c7a78eef8e52 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -56,11 +56,25 @@ struct read_event {
56 u64 id; 56 u64 id;
57}; 57};
58 58
59struct sample_event{ 59struct sample_event {
60 struct perf_event_header header; 60 struct perf_event_header header;
61 u64 array[]; 61 u64 array[];
62}; 62};
63 63
64struct sample_data {
65 u64 ip;
66 u32 pid, tid;
67 u64 time;
68 u64 addr;
69 u64 id;
70 u64 stream_id;
71 u32 cpu;
72 u64 period;
73 struct ip_callchain *callchain;
74 u32 raw_size;
75 void *raw_data;
76};
77
64#define BUILD_ID_SIZE 20 78#define BUILD_ID_SIZE 20
65 79
66struct build_id_event { 80struct build_id_event {
@@ -155,5 +169,6 @@ int event__process_task(event_t *self);
155struct addr_location; 169struct addr_location;
156int event__preprocess_sample(const event_t *self, struct addr_location *al, 170int event__preprocess_sample(const event_t *self, struct addr_location *al,
157 symbol_filter_t filter); 171 symbol_filter_t filter);
172int event__parse_sample(event_t *event, u64 type, struct sample_data *data);
158 173
159#endif /* __PERF_RECORD_H */ 174#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 4805e6dfd23c..59a9c0b3033e 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -187,7 +187,9 @@ static int do_write(int fd, const void *buf, size_t size)
187 187
188static int __dsos__write_buildid_table(struct list_head *head, int fd) 188static int __dsos__write_buildid_table(struct list_head *head, int fd)
189{ 189{
190#define NAME_ALIGN 64
190 struct dso *pos; 191 struct dso *pos;
192 static const char zero_buf[NAME_ALIGN];
191 193
192 list_for_each_entry(pos, head, node) { 194 list_for_each_entry(pos, head, node) {
193 int err; 195 int err;
@@ -197,14 +199,17 @@ static int __dsos__write_buildid_table(struct list_head *head, int fd)
197 if (!pos->has_build_id) 199 if (!pos->has_build_id)
198 continue; 200 continue;
199 len = pos->long_name_len + 1; 201 len = pos->long_name_len + 1;
200 len = ALIGN(len, 64); 202 len = ALIGN(len, NAME_ALIGN);
201 memset(&b, 0, sizeof(b)); 203 memset(&b, 0, sizeof(b));
202 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); 204 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
203 b.header.size = sizeof(b) + len; 205 b.header.size = sizeof(b) + len;
204 err = do_write(fd, &b, sizeof(b)); 206 err = do_write(fd, &b, sizeof(b));
205 if (err < 0) 207 if (err < 0)
206 return err; 208 return err;
207 err = do_write(fd, pos->long_name, len); 209 err = do_write(fd, pos->long_name, pos->long_name_len + 1);
210 if (err < 0)
211 return err;
212 err = do_write(fd, zero_buf, len - pos->long_name_len - 1);
208 if (err < 0) 213 if (err < 0)
209 return err; 214 return err;
210 } 215 }
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 9e5dbd66d34d..e5bc0fb016b2 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -197,7 +197,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
197 if (id == config) { 197 if (id == config) {
198 closedir(evt_dir); 198 closedir(evt_dir);
199 closedir(sys_dir); 199 closedir(sys_dir);
200 path = zalloc(sizeof(path)); 200 path = zalloc(sizeof(*path));
201 path->system = malloc(MAX_EVENT_LENGTH); 201 path->system = malloc(MAX_EVENT_LENGTH);
202 if (!path->system) { 202 if (!path->system) {
203 free(path); 203 free(path);
@@ -467,7 +467,6 @@ parse_subsystem_tracepoint_event(char *sys_name, char *flags)
467 while ((evt_ent = readdir(evt_dir))) { 467 while ((evt_ent = readdir(evt_dir))) {
468 char event_opt[MAX_EVOPT_LEN + 1]; 468 char event_opt[MAX_EVOPT_LEN + 1];
469 int len; 469 int len;
470 unsigned int rem = MAX_EVOPT_LEN;
471 470
472 if (!strcmp(evt_ent->d_name, ".") 471 if (!strcmp(evt_ent->d_name, ".")
473 || !strcmp(evt_ent->d_name, "..") 472 || !strcmp(evt_ent->d_name, "..")
@@ -475,20 +474,12 @@ parse_subsystem_tracepoint_event(char *sys_name, char *flags)
475 || !strcmp(evt_ent->d_name, "filter")) 474 || !strcmp(evt_ent->d_name, "filter"))
476 continue; 475 continue;
477 476
478 len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name, 477 len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name,
479 evt_ent->d_name); 478 evt_ent->d_name, flags ? ":" : "",
479 flags ?: "");
480 if (len < 0) 480 if (len < 0)
481 return EVT_FAILED; 481 return EVT_FAILED;
482 482
483 rem -= len;
484 if (flags) {
485 if (rem < strlen(flags) + 1)
486 return EVT_FAILED;
487
488 strcat(event_opt, ":");
489 strcat(event_opt, flags);
490 }
491
492 if (parse_events(NULL, event_opt, 0)) 483 if (parse_events(NULL, event_opt, 0))
493 return EVT_FAILED; 484 return EVT_FAILED;
494 } 485 }
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 6d8af48c925e..efebd5b476b3 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -430,6 +430,9 @@ int usage_with_options_internal(const char * const *usagestr,
430 pos = fprintf(stderr, " "); 430 pos = fprintf(stderr, " ");
431 if (opts->short_name) 431 if (opts->short_name)
432 pos += fprintf(stderr, "-%c", opts->short_name); 432 pos += fprintf(stderr, "-%c", opts->short_name);
433 else
434 pos += fprintf(stderr, " ");
435
433 if (opts->long_name && opts->short_name) 436 if (opts->long_name && opts->short_name)
434 pos += fprintf(stderr, ", "); 437 pos += fprintf(stderr, ", ");
435 if (opts->long_name) 438 if (opts->long_name)
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index cd7fbda5e2a5..d14a4585bcaf 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -48,6 +48,9 @@
48 48
49/* If there is no space to write, returns -E2BIG. */ 49/* If there is no space to write, returns -E2BIG. */
50static int e_snprintf(char *str, size_t size, const char *format, ...) 50static int e_snprintf(char *str, size_t size, const char *format, ...)
51 __attribute__((format(printf, 3, 4)));
52
53static int e_snprintf(char *str, size_t size, const char *format, ...)
51{ 54{
52 int ret; 55 int ret;
53 va_list ap; 56 va_list ap;
@@ -258,7 +261,7 @@ int synthesize_perf_probe_event(struct probe_point *pp)
258 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function, 261 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function,
259 offs, pp->retprobe ? "%return" : "", line); 262 offs, pp->retprobe ? "%return" : "", line);
260 else 263 else
261 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->file, line); 264 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line);
262 if (ret <= 0) 265 if (ret <= 0)
263 goto error; 266 goto error;
264 len = ret; 267 len = ret;
@@ -373,14 +376,32 @@ static void clear_probe_point(struct probe_point *pp)
373 free(pp->args); 376 free(pp->args);
374 for (i = 0; i < pp->found; i++) 377 for (i = 0; i < pp->found; i++)
375 free(pp->probes[i]); 378 free(pp->probes[i]);
376 memset(pp, 0, sizeof(pp)); 379 memset(pp, 0, sizeof(*pp));
380}
381
382/* Show an event */
383static void show_perf_probe_event(const char *group, const char *event,
384 const char *place, struct probe_point *pp)
385{
386 int i;
387 char buf[128];
388
389 e_snprintf(buf, 128, "%s:%s", group, event);
390 printf(" %-40s (on %s", buf, place);
391
392 if (pp->nr_args > 0) {
393 printf(" with");
394 for (i = 0; i < pp->nr_args; i++)
395 printf(" %s", pp->args[i]);
396 }
397 printf(")\n");
377} 398}
378 399
379/* List up current perf-probe events */ 400/* List up current perf-probe events */
380void show_perf_probe_events(void) 401void show_perf_probe_events(void)
381{ 402{
382 unsigned int i; 403 unsigned int i;
383 int fd; 404 int fd, nr;
384 char *group, *event; 405 char *group, *event;
385 struct probe_point pp; 406 struct probe_point pp;
386 struct strlist *rawlist; 407 struct strlist *rawlist;
@@ -393,8 +414,13 @@ void show_perf_probe_events(void)
393 for (i = 0; i < strlist__nr_entries(rawlist); i++) { 414 for (i = 0; i < strlist__nr_entries(rawlist); i++) {
394 ent = strlist__entry(rawlist, i); 415 ent = strlist__entry(rawlist, i);
395 parse_trace_kprobe_event(ent->s, &group, &event, &pp); 416 parse_trace_kprobe_event(ent->s, &group, &event, &pp);
417 /* Synthesize only event probe point */
418 nr = pp.nr_args;
419 pp.nr_args = 0;
396 synthesize_perf_probe_event(&pp); 420 synthesize_perf_probe_event(&pp);
397 printf("[%s:%s]\t%s\n", group, event, pp.probes[0]); 421 pp.nr_args = nr;
422 /* Show an event */
423 show_perf_probe_event(group, event, pp.probes[0], &pp);
398 free(group); 424 free(group);
399 free(event); 425 free(event);
400 clear_probe_point(&pp); 426 clear_probe_point(&pp);
@@ -404,21 +430,28 @@ void show_perf_probe_events(void)
404} 430}
405 431
406/* Get current perf-probe event names */ 432/* Get current perf-probe event names */
407static struct strlist *get_perf_event_names(int fd) 433static struct strlist *get_perf_event_names(int fd, bool include_group)
408{ 434{
409 unsigned int i; 435 unsigned int i;
410 char *group, *event; 436 char *group, *event;
437 char buf[128];
411 struct strlist *sl, *rawlist; 438 struct strlist *sl, *rawlist;
412 struct str_node *ent; 439 struct str_node *ent;
413 440
414 rawlist = get_trace_kprobe_event_rawlist(fd); 441 rawlist = get_trace_kprobe_event_rawlist(fd);
415 442
416 sl = strlist__new(false, NULL); 443 sl = strlist__new(true, NULL);
417 for (i = 0; i < strlist__nr_entries(rawlist); i++) { 444 for (i = 0; i < strlist__nr_entries(rawlist); i++) {
418 ent = strlist__entry(rawlist, i); 445 ent = strlist__entry(rawlist, i);
419 parse_trace_kprobe_event(ent->s, &group, &event, NULL); 446 parse_trace_kprobe_event(ent->s, &group, &event, NULL);
420 strlist__add(sl, event); 447 if (include_group) {
448 if (e_snprintf(buf, 128, "%s:%s", group, event) < 0)
449 die("Failed to copy group:event name.");
450 strlist__add(sl, buf);
451 } else
452 strlist__add(sl, event);
421 free(group); 453 free(group);
454 free(event);
422 } 455 }
423 456
424 strlist__delete(rawlist); 457 strlist__delete(rawlist);
@@ -426,24 +459,30 @@ static struct strlist *get_perf_event_names(int fd)
426 return sl; 459 return sl;
427} 460}
428 461
429static int write_trace_kprobe_event(int fd, const char *buf) 462static void write_trace_kprobe_event(int fd, const char *buf)
430{ 463{
431 int ret; 464 int ret;
432 465
466 pr_debug("Writing event: %s\n", buf);
433 ret = write(fd, buf, strlen(buf)); 467 ret = write(fd, buf, strlen(buf));
434 if (ret <= 0) 468 if (ret <= 0)
435 die("Failed to create event."); 469 die("Failed to write event: %s", strerror(errno));
436 else
437 printf("Added new event: %s\n", buf);
438
439 return ret;
440} 470}
441 471
442static void get_new_event_name(char *buf, size_t len, const char *base, 472static void get_new_event_name(char *buf, size_t len, const char *base,
443 struct strlist *namelist) 473 struct strlist *namelist)
444{ 474{
445 int i, ret; 475 int i, ret;
446 for (i = 0; i < MAX_EVENT_INDEX; i++) { 476
477 /* Try no suffix */
478 ret = e_snprintf(buf, len, "%s", base);
479 if (ret < 0)
480 die("snprintf() failed: %s", strerror(-ret));
481 if (!strlist__has_entry(namelist, buf))
482 return;
483
484 /* Try to add suffix */
485 for (i = 1; i < MAX_EVENT_INDEX; i++) {
447 ret = e_snprintf(buf, len, "%s_%d", base, i); 486 ret = e_snprintf(buf, len, "%s_%d", base, i);
448 if (ret < 0) 487 if (ret < 0)
449 die("snprintf() failed: %s", strerror(-ret)); 488 die("snprintf() failed: %s", strerror(-ret));
@@ -464,7 +503,7 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes)
464 503
465 fd = open_kprobe_events(O_RDWR, O_APPEND); 504 fd = open_kprobe_events(O_RDWR, O_APPEND);
466 /* Get current event names */ 505 /* Get current event names */
467 namelist = get_perf_event_names(fd); 506 namelist = get_perf_event_names(fd, false);
468 507
469 for (j = 0; j < nr_probes; j++) { 508 for (j = 0; j < nr_probes; j++) {
470 pp = probes + j; 509 pp = probes + j;
@@ -476,9 +515,73 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes)
476 PERFPROBE_GROUP, event, 515 PERFPROBE_GROUP, event,
477 pp->probes[i]); 516 pp->probes[i]);
478 write_trace_kprobe_event(fd, buf); 517 write_trace_kprobe_event(fd, buf);
518 printf("Added new event:\n");
519 /* Get the first parameter (probe-point) */
520 sscanf(pp->probes[i], "%s", buf);
521 show_perf_probe_event(PERFPROBE_GROUP, event,
522 buf, pp);
479 /* Add added event name to namelist */ 523 /* Add added event name to namelist */
480 strlist__add(namelist, event); 524 strlist__add(namelist, event);
481 } 525 }
482 } 526 }
527 /* Show how to use the event. */
528 printf("\nYou can now use it on all perf tools, such as:\n\n");
529 printf("\tperf record -e %s:%s -a sleep 1\n\n", PERFPROBE_GROUP, event);
530
531 strlist__delete(namelist);
532 close(fd);
533}
534
535static void del_trace_kprobe_event(int fd, const char *group,
536 const char *event, struct strlist *namelist)
537{
538 char buf[128];
539
540 if (e_snprintf(buf, 128, "%s:%s", group, event) < 0)
541 die("Failed to copy event.");
542 if (!strlist__has_entry(namelist, buf)) {
543 pr_warning("Warning: event \"%s\" is not found.\n", buf);
544 return;
545 }
546 /* Convert from perf-probe event to trace-kprobe event */
547 if (e_snprintf(buf, 128, "-:%s/%s", group, event) < 0)
548 die("Failed to copy event.");
549
550 write_trace_kprobe_event(fd, buf);
551 printf("Remove event: %s:%s\n", group, event);
552}
553
554void del_trace_kprobe_events(struct strlist *dellist)
555{
556 int fd;
557 unsigned int i;
558 const char *group, *event;
559 char *p, *str;
560 struct str_node *ent;
561 struct strlist *namelist;
562
563 fd = open_kprobe_events(O_RDWR, O_APPEND);
564 /* Get current event names */
565 namelist = get_perf_event_names(fd, true);
566
567 for (i = 0; i < strlist__nr_entries(dellist); i++) {
568 ent = strlist__entry(dellist, i);
569 str = strdup(ent->s);
570 if (!str)
571 die("Failed to copy event.");
572 p = strchr(str, ':');
573 if (p) {
574 group = str;
575 *p = '\0';
576 event = p + 1;
577 } else {
578 group = PERFPROBE_GROUP;
579 event = str;
580 }
581 del_trace_kprobe_event(fd, group, event, namelist);
582 free(str);
583 }
584 strlist__delete(namelist);
483 close(fd); 585 close(fd);
484} 586}
587
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 0c6fe56fe38a..f752159124ae 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -10,6 +10,7 @@ extern void parse_trace_kprobe_event(const char *str, char **group,
10 char **event, struct probe_point *pp); 10 char **event, struct probe_point *pp);
11extern int synthesize_trace_kprobe_event(struct probe_point *pp); 11extern int synthesize_trace_kprobe_event(struct probe_point *pp);
12extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes); 12extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes);
13extern void del_trace_kprobe_events(struct strlist *dellist);
13extern void show_perf_probe_events(void); 14extern void show_perf_probe_events(void);
14 15
15/* Maximum index number of event-name postfix */ 16/* Maximum index number of event-name postfix */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 293cdfc1b8ca..4585f1d86792 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -106,7 +106,7 @@ static int strtailcmp(const char *s1, const char *s2)
106{ 106{
107 int i1 = strlen(s1); 107 int i1 = strlen(s1);
108 int i2 = strlen(s2); 108 int i2 = strlen(s2);
109 while (--i1 > 0 && --i2 > 0) { 109 while (--i1 >= 0 && --i2 >= 0) {
110 if (s1[i1] != s2[i2]) 110 if (s1[i1] != s2[i2])
111 return s1[i1] - s2[i2]; 111 return s1[i1] - s2[i2];
112 } 112 }
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index fffcb937cdcb..e7508ad3450f 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -938,8 +938,9 @@ static bool __dsos__read_build_ids(struct list_head *head)
938 938
939bool dsos__read_build_ids(void) 939bool dsos__read_build_ids(void)
940{ 940{
941 return __dsos__read_build_ids(&dsos__kernel) || 941 bool kbuildids = __dsos__read_build_ids(&dsos__kernel),
942 __dsos__read_build_ids(&dsos__user); 942 ubuildids = __dsos__read_build_ids(&dsos__user);
943 return kbuildids || ubuildids;
943} 944}
944 945
945/* 946/*
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 0302405aa2ca..c5c32be040bf 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -177,7 +177,7 @@ void parse_proc_kallsyms(char *file, unsigned int size __unused)
177 func_count++; 177 func_count++;
178 } 178 }
179 179
180 func_list = malloc_or_die(sizeof(*func_list) * func_count + 1); 180 func_list = malloc_or_die(sizeof(*func_list) * (func_count + 1));
181 181
182 i = 0; 182 i = 0;
183 while (list) { 183 while (list) {
@@ -1477,7 +1477,7 @@ process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1477 goto out_free; 1477 goto out_free;
1478 1478
1479 field = malloc_or_die(sizeof(*field)); 1479 field = malloc_or_die(sizeof(*field));
1480 memset(field, 0, sizeof(field)); 1480 memset(field, 0, sizeof(*field));
1481 1481
1482 value = arg_eval(arg); 1482 value = arg_eval(arg);
1483 field->value = strdup(value); 1483 field->value = strdup(value);
diff --git a/tools/perf/util/trace-event-perl.c b/tools/perf/util/trace-event-perl.c
index 51e833fd58c3..a5ffe60db5d6 100644
--- a/tools/perf/util/trace-event-perl.c
+++ b/tools/perf/util/trace-event-perl.c
@@ -32,9 +32,6 @@
32 32
33void xs_init(pTHX); 33void xs_init(pTHX);
34 34
35void boot_Perf__Trace__Context(pTHX_ CV *cv);
36void boot_DynaLoader(pTHX_ CV *cv);
37
38void xs_init(pTHX) 35void xs_init(pTHX)
39{ 36{
40 const char *file = __FILE__; 37 const char *file = __FILE__;
@@ -573,26 +570,72 @@ struct scripting_ops perl_scripting_ops = {
573 .generate_script = perl_generate_script, 570 .generate_script = perl_generate_script,
574}; 571};
575 572
576#ifdef NO_LIBPERL 573static void print_unsupported_msg(void)
577void setup_perl_scripting(void)
578{ 574{
579 fprintf(stderr, "Perl scripting not supported." 575 fprintf(stderr, "Perl scripting not supported."
580 " Install libperl and rebuild perf to enable it. e.g. " 576 " Install libperl and rebuild perf to enable it.\n"
581 "apt-get install libperl-dev (ubuntu), yum install " 577 "For example:\n # apt-get install libperl-dev (ubuntu)"
582 "perl-ExtUtils-Embed (Fedora), etc.\n"); 578 "\n # yum install perl-ExtUtils-Embed (Fedora)"
579 "\n etc.\n");
583} 580}
584#else 581
585void setup_perl_scripting(void) 582static int perl_start_script_unsupported(const char *script __unused)
583{
584 print_unsupported_msg();
585
586 return -1;
587}
588
589static int perl_stop_script_unsupported(void)
590{
591 return 0;
592}
593
594static void perl_process_event_unsupported(int cpu __unused,
595 void *data __unused,
596 int size __unused,
597 unsigned long long nsecs __unused,
598 char *comm __unused)
599{
600}
601
602static int perl_generate_script_unsupported(const char *outfile __unused)
603{
604 print_unsupported_msg();
605
606 return -1;
607}
608
609struct scripting_ops perl_scripting_unsupported_ops = {
610 .name = "Perl",
611 .start_script = perl_start_script_unsupported,
612 .stop_script = perl_stop_script_unsupported,
613 .process_event = perl_process_event_unsupported,
614 .generate_script = perl_generate_script_unsupported,
615};
616
617static void register_perl_scripting(struct scripting_ops *scripting_ops)
586{ 618{
587 int err; 619 int err;
588 err = script_spec_register("Perl", &perl_scripting_ops); 620 err = script_spec_register("Perl", scripting_ops);
589 if (err) 621 if (err)
590 die("error registering Perl script extension"); 622 die("error registering Perl script extension");
591 623
592 err = script_spec_register("pl", &perl_scripting_ops); 624 err = script_spec_register("pl", scripting_ops);
593 if (err) 625 if (err)
594 die("error registering pl script extension"); 626 die("error registering pl script extension");
595 627
596 scripting_context = malloc(sizeof(struct scripting_context)); 628 scripting_context = malloc(sizeof(struct scripting_context));
597} 629}
630
631#ifdef NO_LIBPERL
632void setup_perl_scripting(void)
633{
634 register_perl_scripting(&perl_scripting_unsupported_ops);
635}
636#else
637void setup_perl_scripting(void)
638{
639 register_perl_scripting(&perl_scripting_ops);
640}
598#endif 641#endif
diff --git a/tools/perf/util/trace-event-perl.h b/tools/perf/util/trace-event-perl.h
index 8fe0d866fe1a..e88fb26137bb 100644
--- a/tools/perf/util/trace-event-perl.h
+++ b/tools/perf/util/trace-event-perl.h
@@ -34,9 +34,13 @@ typedef int INTERP;
34#define dXSUB_SYS 34#define dXSUB_SYS
35#define pTHX_ 35#define pTHX_
36static inline void newXS(const char *a, void *b, const char *c) {} 36static inline void newXS(const char *a, void *b, const char *c) {}
37static void boot_Perf__Trace__Context(pTHX_ CV *cv) {}
38static void boot_DynaLoader(pTHX_ CV *cv) {}
37#else 39#else
38#include <EXTERN.h> 40#include <EXTERN.h>
39#include <perl.h> 41#include <perl.h>
42void boot_Perf__Trace__Context(pTHX_ CV *cv);
43void boot_DynaLoader(pTHX_ CV *cv);
40typedef PerlInterpreter * INTERP; 44typedef PerlInterpreter * INTERP;
41#endif 45#endif
42 46
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 342dfdd43f87..1744422cafcb 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -145,8 +145,9 @@ static void read_proc_kallsyms(void)
145 if (!size) 145 if (!size)
146 return; 146 return;
147 147
148 buf = malloc_or_die(size); 148 buf = malloc_or_die(size + 1);
149 read_or_die(buf, size); 149 read_or_die(buf, size);
150 buf[size] = '\0';
150 151
151 parse_proc_kallsyms(buf, size); 152 parse_proc_kallsyms(buf, size);
152 153