aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2010-12-07 01:51:14 -0500
committerIngo Molnar <mingo@elte.hu>2010-12-07 01:51:14 -0500
commit75b5293a5d176cd9caf6dc590da4f3458c048c3c (patch)
tree40929d6108c662d6eb4c65f900312a37d0d6d566 /tools/perf
parent10a18d7dc0d9f12483c95ffc234118e9b80edfeb (diff)
parentce47dc56a2241dc035160a85bc5e34283cdd622c (diff)
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-record.txt5
-rw-r--r--tools/perf/builtin-annotate.c6
-rw-r--r--tools/perf/builtin-diff.c11
-rw-r--r--tools/perf/builtin-inject.c39
-rw-r--r--tools/perf/builtin-kmem.c24
-rw-r--r--tools/perf/builtin-lock.c15
-rw-r--r--tools/perf/builtin-record.c23
-rw-r--r--tools/perf/builtin-report.c15
-rw-r--r--tools/perf/builtin-sched.c24
-rw-r--r--tools/perf/builtin-script.c44
-rw-r--r--tools/perf/builtin-timechart.c43
-rw-r--r--tools/perf/builtin-top.c12
-rw-r--r--tools/perf/util/build-id.c7
-rw-r--r--tools/perf/util/event.c341
-rw-r--r--tools/perf/util/event.h27
-rw-r--r--tools/perf/util/header.c32
-rw-r--r--tools/perf/util/header.h1
-rw-r--r--tools/perf/util/hist.h2
-rw-r--r--tools/perf/util/parse-options.h4
-rw-r--r--tools/perf/util/session.c226
-rw-r--r--tools/perf/util/session.h12
-rw-r--r--tools/perf/util/sort.c6
22 files changed, 608 insertions, 311 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 0ad1bc75ab49..52462ae26455 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -108,6 +108,11 @@ OPTIONS
108--data:: 108--data::
109 Sample addresses. 109 Sample addresses.
110 110
111-T::
112--timestamp::
113 Sample timestamps. Use it with 'perf report -D' to see the timestamps,
114 for instance.
115
111-n:: 116-n::
112--no-samples:: 117--no-samples::
113 Don't sample. 118 Don't sample.
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 6d5604d8df95..569a2761b90a 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -58,12 +58,12 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
58 return hist_entry__inc_addr_samples(he, al->addr); 58 return hist_entry__inc_addr_samples(he, al->addr);
59} 59}
60 60
61static int process_sample_event(event_t *event, struct perf_session *session) 61static int process_sample_event(event_t *event, struct sample_data *sample,
62 struct perf_session *session)
62{ 63{
63 struct addr_location al; 64 struct addr_location al;
64 struct sample_data data;
65 65
66 if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { 66 if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
67 pr_warning("problem processing %d event, skipping it.\n", 67 pr_warning("problem processing %d event, skipping it.\n",
68 event->header.type); 68 event->header.type);
69 return -1; 69 return -1;
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 221b823bc26f..5e1a043aae03 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -30,12 +30,13 @@ static int hists__add_entry(struct hists *self,
30 return -ENOMEM; 30 return -ENOMEM;
31} 31}
32 32
33static int diff__process_sample_event(event_t *event, struct perf_session *session) 33static int diff__process_sample_event(event_t *event,
34 struct sample_data *sample,
35 struct perf_session *session)
34{ 36{
35 struct addr_location al; 37 struct addr_location al;
36 struct sample_data data = { .period = 1, };
37 38
38 if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { 39 if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
39 pr_warning("problem processing %d event, skipping it.\n", 40 pr_warning("problem processing %d event, skipping it.\n",
40 event->header.type); 41 event->header.type);
41 return -1; 42 return -1;
@@ -44,12 +45,12 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi
44 if (al.filtered || al.sym == NULL) 45 if (al.filtered || al.sym == NULL)
45 return 0; 46 return 0;
46 47
47 if (hists__add_entry(&session->hists, &al, data.period)) { 48 if (hists__add_entry(&session->hists, &al, sample->period)) {
48 pr_warning("problem incrementing symbol period, skipping event\n"); 49 pr_warning("problem incrementing symbol period, skipping event\n");
49 return -1; 50 return -1;
50 } 51 }
51 52
52 session->hists.stats.total_period += data.period; 53 session->hists.stats.total_period += sample->period;
53 return 0; 54 return 0;
54} 55}
55 56
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 8e3e47b064ce..4b66b8579410 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -16,8 +16,8 @@
16static char const *input_name = "-"; 16static char const *input_name = "-";
17static bool inject_build_ids; 17static bool inject_build_ids;
18 18
19static int event__repipe(event_t *event __used, 19static int event__repipe_synth(event_t *event,
20 struct perf_session *session __used) 20 struct perf_session *session __used)
21{ 21{
22 uint32_t size; 22 uint32_t size;
23 void *buf = event; 23 void *buf = event;
@@ -36,22 +36,30 @@ static int event__repipe(event_t *event __used,
36 return 0; 36 return 0;
37} 37}
38 38
39static int event__repipe_mmap(event_t *self, struct perf_session *session) 39static int event__repipe(event_t *event, struct sample_data *sample __used,
40 struct perf_session *session)
41{
42 return event__repipe_synth(event, session);
43}
44
45static int event__repipe_mmap(event_t *self, struct sample_data *sample,
46 struct perf_session *session)
40{ 47{
41 int err; 48 int err;
42 49
43 err = event__process_mmap(self, session); 50 err = event__process_mmap(self, sample, session);
44 event__repipe(self, session); 51 event__repipe(self, sample, session);
45 52
46 return err; 53 return err;
47} 54}
48 55
49static int event__repipe_task(event_t *self, struct perf_session *session) 56static int event__repipe_task(event_t *self, struct sample_data *sample,
57 struct perf_session *session)
50{ 58{
51 int err; 59 int err;
52 60
53 err = event__process_task(self, session); 61 err = event__process_task(self, sample, session);
54 event__repipe(self, session); 62 event__repipe(self, sample, session);
55 63
56 return err; 64 return err;
57} 65}
@@ -61,7 +69,7 @@ static int event__repipe_tracing_data(event_t *self,
61{ 69{
62 int err; 70 int err;
63 71
64 event__repipe(self, session); 72 event__repipe_synth(self, session);
65 err = event__process_tracing_data(self, session); 73 err = event__process_tracing_data(self, session);
66 74
67 return err; 75 return err;
@@ -111,7 +119,8 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
111 return 0; 119 return 0;
112} 120}
113 121
114static int event__inject_buildid(event_t *event, struct perf_session *session) 122static int event__inject_buildid(event_t *event, struct sample_data *sample,
123 struct perf_session *session)
115{ 124{
116 struct addr_location al; 125 struct addr_location al;
117 struct thread *thread; 126 struct thread *thread;
@@ -146,7 +155,7 @@ static int event__inject_buildid(event_t *event, struct perf_session *session)
146 } 155 }
147 156
148repipe: 157repipe:
149 event__repipe(event, session); 158 event__repipe(event, sample, session);
150 return 0; 159 return 0;
151} 160}
152 161
@@ -160,10 +169,10 @@ struct perf_event_ops inject_ops = {
160 .read = event__repipe, 169 .read = event__repipe,
161 .throttle = event__repipe, 170 .throttle = event__repipe,
162 .unthrottle = event__repipe, 171 .unthrottle = event__repipe,
163 .attr = event__repipe, 172 .attr = event__repipe_synth,
164 .event_type = event__repipe, 173 .event_type = event__repipe_synth,
165 .tracing_data = event__repipe, 174 .tracing_data = event__repipe_synth,
166 .build_id = event__repipe, 175 .build_id = event__repipe_synth,
167}; 176};
168 177
169extern volatile int session_done; 178extern volatile int session_done;
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 31f60a2535e0..c9620ff6496f 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -304,22 +304,11 @@ process_raw_event(event_t *raw_event __used, void *data,
304 } 304 }
305} 305}
306 306
307static int process_sample_event(event_t *event, struct perf_session *session) 307static int process_sample_event(event_t *event, struct sample_data *sample,
308 struct perf_session *session)
308{ 309{
309 struct sample_data data; 310 struct thread *thread = perf_session__findnew(session, event->ip.pid);
310 struct thread *thread;
311 311
312 memset(&data, 0, sizeof(data));
313 data.time = -1;
314 data.cpu = -1;
315 data.period = 1;
316
317 event__parse_sample(event, session->sample_type, &data);
318
319 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
320 data.pid, data.tid, data.ip, data.period);
321
322 thread = perf_session__findnew(session, event->ip.pid);
323 if (thread == NULL) { 312 if (thread == NULL) {
324 pr_debug("problem processing %d event, skipping it.\n", 313 pr_debug("problem processing %d event, skipping it.\n",
325 event->header.type); 314 event->header.type);
@@ -328,8 +317,8 @@ static int process_sample_event(event_t *event, struct perf_session *session)
328 317
329 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 318 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
330 319
331 process_raw_event(event, data.raw_data, data.cpu, 320 process_raw_event(event, sample->raw_data, sample->cpu,
332 data.time, thread); 321 sample->time, thread);
333 322
334 return 0; 323 return 0;
335} 324}
@@ -747,6 +736,9 @@ static int __cmd_record(int argc, const char **argv)
747 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 736 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
748 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 737 rec_argv = calloc(rec_argc + 1, sizeof(char *));
749 738
739 if (rec_argv == NULL)
740 return -ENOMEM;
741
750 for (i = 0; i < ARRAY_SIZE(record_args); i++) 742 for (i = 0; i < ARRAY_SIZE(record_args); i++)
751 rec_argv[i] = strdup(record_args[i]); 743 rec_argv[i] = strdup(record_args[i]);
752 744
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 8452a2ae2191..b41b4492b1cc 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -834,22 +834,18 @@ static void dump_info(void)
834 die("Unknown type of information\n"); 834 die("Unknown type of information\n");
835} 835}
836 836
837static int process_sample_event(event_t *self, struct perf_session *s) 837static int process_sample_event(event_t *self, struct sample_data *sample,
838 struct perf_session *s)
838{ 839{
839 struct sample_data data; 840 struct thread *thread = perf_session__findnew(s, sample->tid);
840 struct thread *thread;
841 841
842 bzero(&data, sizeof(data));
843 event__parse_sample(self, s->sample_type, &data);
844
845 thread = perf_session__findnew(s, data.tid);
846 if (thread == NULL) { 842 if (thread == NULL) {
847 pr_debug("problem processing %d event, skipping it.\n", 843 pr_debug("problem processing %d event, skipping it.\n",
848 self->header.type); 844 self->header.type);
849 return -1; 845 return -1;
850 } 846 }
851 847
852 process_raw_event(data.raw_data, data.cpu, data.time, thread); 848 process_raw_event(sample->raw_data, sample->cpu, sample->time, thread);
853 849
854 return 0; 850 return 0;
855} 851}
@@ -947,6 +943,9 @@ static int __cmd_record(int argc, const char **argv)
947 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 943 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
948 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 944 rec_argv = calloc(rec_argc + 1, sizeof(char *));
949 945
946 if (rec_argv == NULL)
947 return -ENOMEM;
948
950 for (i = 0; i < ARRAY_SIZE(record_args); i++) 949 for (i = 0; i < ARRAY_SIZE(record_args); i++)
951 rec_argv[i] = strdup(record_args[i]); 950 rec_argv[i] = strdup(record_args[i]);
952 951
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 024e1441d76b..699dd2149c4b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -36,6 +36,7 @@ static int *fd[MAX_NR_CPUS][MAX_COUNTERS];
36 36
37static u64 user_interval = ULLONG_MAX; 37static u64 user_interval = ULLONG_MAX;
38static u64 default_interval = 0; 38static u64 default_interval = 0;
39static u64 sample_type;
39 40
40static int nr_cpus = 0; 41static int nr_cpus = 0;
41static unsigned int page_size; 42static unsigned int page_size;
@@ -48,6 +49,7 @@ static const char *output_name = "perf.data";
48static int group = 0; 49static int group = 0;
49static int realtime_prio = 0; 50static int realtime_prio = 0;
50static bool raw_samples = false; 51static bool raw_samples = false;
52static bool sample_id_all_avail = true;
51static bool system_wide = false; 53static bool system_wide = false;
52static pid_t target_pid = -1; 54static pid_t target_pid = -1;
53static pid_t target_tid = -1; 55static pid_t target_tid = -1;
@@ -60,6 +62,7 @@ static bool call_graph = false;
60static bool inherit_stat = false; 62static bool inherit_stat = false;
61static bool no_samples = false; 63static bool no_samples = false;
62static bool sample_address = false; 64static bool sample_address = false;
65static bool sample_time = false;
63static bool no_buildid = false; 66static bool no_buildid = false;
64static bool no_buildid_cache = false; 67static bool no_buildid_cache = false;
65 68
@@ -129,6 +132,7 @@ static void write_output(void *buf, size_t size)
129} 132}
130 133
131static int process_synthesized_event(event_t *event, 134static int process_synthesized_event(event_t *event,
135 struct sample_data *sample __used,
132 struct perf_session *self __used) 136 struct perf_session *self __used)
133{ 137{
134 write_output(event, event->header.size); 138 write_output(event, event->header.size);
@@ -281,12 +285,18 @@ static void create_counter(int counter, int cpu)
281 if (system_wide) 285 if (system_wide)
282 attr->sample_type |= PERF_SAMPLE_CPU; 286 attr->sample_type |= PERF_SAMPLE_CPU;
283 287
288 if (sample_time)
289 attr->sample_type |= PERF_SAMPLE_TIME;
290
284 if (raw_samples) { 291 if (raw_samples) {
285 attr->sample_type |= PERF_SAMPLE_TIME; 292 attr->sample_type |= PERF_SAMPLE_TIME;
286 attr->sample_type |= PERF_SAMPLE_RAW; 293 attr->sample_type |= PERF_SAMPLE_RAW;
287 attr->sample_type |= PERF_SAMPLE_CPU; 294 attr->sample_type |= PERF_SAMPLE_CPU;
288 } 295 }
289 296
297 if (!sample_type)
298 sample_type = attr->sample_type;
299
290 attr->mmap = track; 300 attr->mmap = track;
291 attr->comm = track; 301 attr->comm = track;
292 attr->inherit = !no_inherit; 302 attr->inherit = !no_inherit;
@@ -294,6 +304,8 @@ static void create_counter(int counter, int cpu)
294 attr->disabled = 1; 304 attr->disabled = 1;
295 attr->enable_on_exec = 1; 305 attr->enable_on_exec = 1;
296 } 306 }
307retry_sample_id:
308 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
297 309
298 for (thread_index = 0; thread_index < thread_num; thread_index++) { 310 for (thread_index = 0; thread_index < thread_num; thread_index++) {
299try_again: 311try_again:
@@ -310,6 +322,12 @@ try_again:
310 else if (err == ENODEV && cpu_list) { 322 else if (err == ENODEV && cpu_list) {
311 die("No such device - did you specify" 323 die("No such device - did you specify"
312 " an out-of-range profile CPU?\n"); 324 " an out-of-range profile CPU?\n");
325 } else if (err == EINVAL && sample_id_all_avail) {
326 /*
327 * Old kernel, no attr->sample_id_type_all field
328 */
329 sample_id_all_avail = false;
330 goto retry_sample_id;
313 } 331 }
314 332
315 /* 333 /*
@@ -642,6 +660,8 @@ static int __cmd_record(int argc, const char **argv)
642 open_counters(cpumap[i]); 660 open_counters(cpumap[i]);
643 } 661 }
644 662
663 perf_session__set_sample_type(session, sample_type);
664
645 if (pipe_output) { 665 if (pipe_output) {
646 err = perf_header__write_pipe(output); 666 err = perf_header__write_pipe(output);
647 if (err < 0) 667 if (err < 0)
@@ -654,6 +674,8 @@ static int __cmd_record(int argc, const char **argv)
654 674
655 post_processing_offset = lseek(output, 0, SEEK_CUR); 675 post_processing_offset = lseek(output, 0, SEEK_CUR);
656 676
677 perf_session__set_sample_id_all(session, sample_id_all_avail);
678
657 if (pipe_output) { 679 if (pipe_output) {
658 err = event__synthesize_attrs(&session->header, 680 err = event__synthesize_attrs(&session->header,
659 process_synthesized_event, 681 process_synthesized_event,
@@ -834,6 +856,7 @@ const struct option record_options[] = {
834 "per thread counts"), 856 "per thread counts"),
835 OPT_BOOLEAN('d', "data", &sample_address, 857 OPT_BOOLEAN('d', "data", &sample_address,
836 "Sample addresses"), 858 "Sample addresses"),
859 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
837 OPT_BOOLEAN('n', "no-samples", &no_samples, 860 OPT_BOOLEAN('n', "no-samples", &no_samples,
838 "don't sample"), 861 "don't sample"),
839 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache, 862 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5de405d45230..904519fba434 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -150,13 +150,13 @@ static int add_event_total(struct perf_session *session,
150 return 0; 150 return 0;
151} 151}
152 152
153static int process_sample_event(event_t *event, struct perf_session *session) 153static int process_sample_event(event_t *event, struct sample_data *sample,
154 struct perf_session *session)
154{ 155{
155 struct sample_data data = { .period = 1, };
156 struct addr_location al; 156 struct addr_location al;
157 struct perf_event_attr *attr; 157 struct perf_event_attr *attr;
158 158
159 if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { 159 if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
160 fprintf(stderr, "problem processing %d event, skipping it.\n", 160 fprintf(stderr, "problem processing %d event, skipping it.\n",
161 event->header.type); 161 event->header.type);
162 return -1; 162 return -1;
@@ -165,14 +165,14 @@ static int process_sample_event(event_t *event, struct perf_session *session)
165 if (al.filtered || (hide_unresolved && al.sym == NULL)) 165 if (al.filtered || (hide_unresolved && al.sym == NULL))
166 return 0; 166 return 0;
167 167
168 if (perf_session__add_hist_entry(session, &al, &data)) { 168 if (perf_session__add_hist_entry(session, &al, sample)) {
169 pr_debug("problem incrementing symbol period, skipping event\n"); 169 pr_debug("problem incrementing symbol period, skipping event\n");
170 return -1; 170 return -1;
171 } 171 }
172 172
173 attr = perf_header__find_attr(data.id, &session->header); 173 attr = perf_header__find_attr(sample->id, &session->header);
174 174
175 if (add_event_total(session, &data, attr)) { 175 if (add_event_total(session, sample, attr)) {
176 pr_debug("problem adding event period\n"); 176 pr_debug("problem adding event period\n");
177 return -1; 177 return -1;
178 } 178 }
@@ -180,7 +180,8 @@ static int process_sample_event(event_t *event, struct perf_session *session)
180 return 0; 180 return 0;
181} 181}
182 182
183static int process_read_event(event_t *event, struct perf_session *session __used) 183static int process_read_event(event_t *event, struct sample_data *sample __used,
184 struct perf_session *session __used)
184{ 185{
185 struct perf_event_attr *attr; 186 struct perf_event_attr *attr;
186 187
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 26523c939791..c7753940aea0 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1606,25 +1606,15 @@ process_raw_event(event_t *raw_event __used, struct perf_session *session,
1606 process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread); 1606 process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread);
1607} 1607}
1608 1608
1609static int process_sample_event(event_t *event, struct perf_session *session) 1609static int process_sample_event(event_t *event, struct sample_data *sample,
1610 struct perf_session *session)
1610{ 1611{
1611 struct sample_data data;
1612 struct thread *thread; 1612 struct thread *thread;
1613 1613
1614 if (!(session->sample_type & PERF_SAMPLE_RAW)) 1614 if (!(session->sample_type & PERF_SAMPLE_RAW))
1615 return 0; 1615 return 0;
1616 1616
1617 memset(&data, 0, sizeof(data)); 1617 thread = perf_session__findnew(session, sample->pid);
1618 data.time = -1;
1619 data.cpu = -1;
1620 data.period = -1;
1621
1622 event__parse_sample(event, session->sample_type, &data);
1623
1624 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
1625 data.pid, data.tid, data.ip, data.period);
1626
1627 thread = perf_session__findnew(session, data.pid);
1628 if (thread == NULL) { 1618 if (thread == NULL) {
1629 pr_debug("problem processing %d event, skipping it.\n", 1619 pr_debug("problem processing %d event, skipping it.\n",
1630 event->header.type); 1620 event->header.type);
@@ -1633,10 +1623,11 @@ static int process_sample_event(event_t *event, struct perf_session *session)
1633 1623
1634 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 1624 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
1635 1625
1636 if (profile_cpu != -1 && profile_cpu != (int)data.cpu) 1626 if (profile_cpu != -1 && profile_cpu != (int)sample->cpu)
1637 return 0; 1627 return 0;
1638 1628
1639 process_raw_event(event, session, data.raw_data, data.cpu, data.time, thread); 1629 process_raw_event(event, session, sample->raw_data, sample->cpu,
1630 sample->time, thread);
1640 1631
1641 return 0; 1632 return 0;
1642} 1633}
@@ -1869,6 +1860,9 @@ static int __cmd_record(int argc, const char **argv)
1869 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 1860 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
1870 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1861 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1871 1862
1863 if (rec_argv)
1864 return -ENOMEM;
1865
1872 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1866 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1873 rec_argv[i] = strdup(record_args[i]); 1867 rec_argv[i] = strdup(record_args[i]);
1874 1868
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 4539551ab40e..54f1ea808db5 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -63,22 +63,11 @@ static int cleanup_scripting(void)
63 63
64static char const *input_name = "perf.data"; 64static char const *input_name = "perf.data";
65 65
66static int process_sample_event(event_t *event, struct perf_session *session) 66static int process_sample_event(event_t *event, struct sample_data *sample,
67 struct perf_session *session)
67{ 68{
68 struct sample_data data; 69 struct thread *thread = perf_session__findnew(session, event->ip.pid);
69 struct thread *thread;
70 70
71 memset(&data, 0, sizeof(data));
72 data.time = -1;
73 data.cpu = -1;
74 data.period = 1;
75
76 event__parse_sample(event, session->sample_type, &data);
77
78 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
79 data.pid, data.tid, data.ip, data.period);
80
81 thread = perf_session__findnew(session, event->ip.pid);
82 if (thread == NULL) { 71 if (thread == NULL) {
83 pr_debug("problem processing %d event, skipping it.\n", 72 pr_debug("problem processing %d event, skipping it.\n",
84 event->header.type); 73 event->header.type);
@@ -87,13 +76,13 @@ static int process_sample_event(event_t *event, struct perf_session *session)
87 76
88 if (session->sample_type & PERF_SAMPLE_RAW) { 77 if (session->sample_type & PERF_SAMPLE_RAW) {
89 if (debug_mode) { 78 if (debug_mode) {
90 if (data.time < last_timestamp) { 79 if (sample->time < last_timestamp) {
91 pr_err("Samples misordered, previous: %llu " 80 pr_err("Samples misordered, previous: %llu "
92 "this: %llu\n", last_timestamp, 81 "this: %llu\n", last_timestamp,
93 data.time); 82 sample->time);
94 nr_unordered++; 83 nr_unordered++;
95 } 84 }
96 last_timestamp = data.time; 85 last_timestamp = sample->time;
97 return 0; 86 return 0;
98 } 87 }
99 /* 88 /*
@@ -101,18 +90,19 @@ static int process_sample_event(event_t *event, struct perf_session *session)
101 * field, although it should be the same than this perf 90 * field, although it should be the same than this perf
102 * event pid 91 * event pid
103 */ 92 */
104 scripting_ops->process_event(data.cpu, data.raw_data, 93 scripting_ops->process_event(sample->cpu, sample->raw_data,
105 data.raw_size, 94 sample->raw_size,
106 data.time, thread->comm); 95 sample->time, thread->comm);
107 } 96 }
108 97
109 session->hists.stats.total_period += data.period; 98 session->hists.stats.total_period += sample->period;
110 return 0; 99 return 0;
111} 100}
112 101
113static u64 nr_lost; 102static u64 nr_lost;
114 103
115static int process_lost_event(event_t *event, struct perf_session *session __used) 104static int process_lost_event(event_t *event, struct sample_data *sample __used,
105 struct perf_session *session __used)
116{ 106{
117 nr_lost += event->lost.lost; 107 nr_lost += event->lost.lost;
118 108
@@ -397,10 +387,10 @@ out_delete_desc:
397 return NULL; 387 return NULL;
398} 388}
399 389
400static char *ends_with(char *str, const char *suffix) 390static const char *ends_with(const char *str, const char *suffix)
401{ 391{
402 size_t suffix_len = strlen(suffix); 392 size_t suffix_len = strlen(suffix);
403 char *p = str; 393 const char *p = str;
404 394
405 if (strlen(str) > suffix_len) { 395 if (strlen(str) > suffix_len) {
406 p = str + strlen(str) - suffix_len; 396 p = str + strlen(str) - suffix_len;
@@ -492,7 +482,7 @@ static int list_available_scripts(const struct option *opt __used,
492 482
493 for_each_script(lang_path, lang_dir, script_dirent, script_next) { 483 for_each_script(lang_path, lang_dir, script_dirent, script_next) {
494 script_root = strdup(script_dirent.d_name); 484 script_root = strdup(script_dirent.d_name);
495 str = ends_with(script_root, REPORT_SUFFIX); 485 str = (char *)ends_with(script_root, REPORT_SUFFIX);
496 if (str) { 486 if (str) {
497 *str = '\0'; 487 *str = '\0';
498 desc = script_desc__findnew(script_root); 488 desc = script_desc__findnew(script_root);
@@ -540,7 +530,7 @@ static char *get_script_path(const char *script_root, const char *suffix)
540 530
541 for_each_script(lang_path, lang_dir, script_dirent, script_next) { 531 for_each_script(lang_path, lang_dir, script_dirent, script_next) {
542 __script_root = strdup(script_dirent.d_name); 532 __script_root = strdup(script_dirent.d_name);
543 str = ends_with(__script_root, suffix); 533 str = (char *)ends_with(__script_root, suffix);
544 if (str) { 534 if (str) {
545 *str = '\0'; 535 *str = '\0';
546 if (strcmp(__script_root, script_root)) 536 if (strcmp(__script_root, script_root))
@@ -560,7 +550,7 @@ static char *get_script_path(const char *script_root, const char *suffix)
560 550
561static bool is_top_script(const char *script_path) 551static bool is_top_script(const char *script_path)
562{ 552{
563 return ends_with((char *)script_path, "top") == NULL ? false : true; 553 return ends_with(script_path, "top") == NULL ? false : true;
564} 554}
565 555
566static int has_required_arg(char *script_path) 556static int has_required_arg(char *script_path)
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 9bcc38f0b706..d2fc46103f83 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -272,19 +272,22 @@ static int cpus_cstate_state[MAX_CPUS];
272static u64 cpus_pstate_start_times[MAX_CPUS]; 272static u64 cpus_pstate_start_times[MAX_CPUS];
273static u64 cpus_pstate_state[MAX_CPUS]; 273static u64 cpus_pstate_state[MAX_CPUS];
274 274
275static int process_comm_event(event_t *event, struct perf_session *session __used) 275static int process_comm_event(event_t *event, struct sample_data *sample __used,
276 struct perf_session *session __used)
276{ 277{
277 pid_set_comm(event->comm.tid, event->comm.comm); 278 pid_set_comm(event->comm.tid, event->comm.comm);
278 return 0; 279 return 0;
279} 280}
280 281
281static int process_fork_event(event_t *event, struct perf_session *session __used) 282static int process_fork_event(event_t *event, struct sample_data *sample __used,
283 struct perf_session *session __used)
282{ 284{
283 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); 285 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
284 return 0; 286 return 0;
285} 287}
286 288
287static int process_exit_event(event_t *event, struct perf_session *session __used) 289static int process_exit_event(event_t *event, struct sample_data *sample __used,
290 struct perf_session *session __used)
288{ 291{
289 pid_exit(event->fork.pid, event->fork.time); 292 pid_exit(event->fork.pid, event->fork.time);
290 return 0; 293 return 0;
@@ -470,24 +473,21 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
470} 473}
471 474
472 475
473static int process_sample_event(event_t *event, struct perf_session *session) 476static int process_sample_event(event_t *event __used,
477 struct sample_data *sample,
478 struct perf_session *session)
474{ 479{
475 struct sample_data data;
476 struct trace_entry *te; 480 struct trace_entry *te;
477 481
478 memset(&data, 0, sizeof(data));
479
480 event__parse_sample(event, session->sample_type, &data);
481
482 if (session->sample_type & PERF_SAMPLE_TIME) { 482 if (session->sample_type & PERF_SAMPLE_TIME) {
483 if (!first_time || first_time > data.time) 483 if (!first_time || first_time > sample->time)
484 first_time = data.time; 484 first_time = sample->time;
485 if (last_time < data.time) 485 if (last_time < sample->time)
486 last_time = data.time; 486 last_time = sample->time;
487 } 487 }
488 488
489 te = (void *)data.raw_data; 489 te = (void *)sample->raw_data;
490 if (session->sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) { 490 if (session->sample_type & PERF_SAMPLE_RAW && sample->raw_size > 0) {
491 char *event_str; 491 char *event_str;
492 struct power_entry *pe; 492 struct power_entry *pe;
493 493
@@ -499,19 +499,19 @@ static int process_sample_event(event_t *event, struct perf_session *session)
499 return 0; 499 return 0;
500 500
501 if (strcmp(event_str, "power:power_start") == 0) 501 if (strcmp(event_str, "power:power_start") == 0)
502 c_state_start(pe->cpu_id, data.time, pe->value); 502 c_state_start(pe->cpu_id, sample->time, pe->value);
503 503
504 if (strcmp(event_str, "power:power_end") == 0) 504 if (strcmp(event_str, "power:power_end") == 0)
505 c_state_end(pe->cpu_id, data.time); 505 c_state_end(pe->cpu_id, sample->time);
506 506
507 if (strcmp(event_str, "power:power_frequency") == 0) 507 if (strcmp(event_str, "power:power_frequency") == 0)
508 p_state_change(pe->cpu_id, data.time, pe->value); 508 p_state_change(pe->cpu_id, sample->time, pe->value);
509 509
510 if (strcmp(event_str, "sched:sched_wakeup") == 0) 510 if (strcmp(event_str, "sched:sched_wakeup") == 0)
511 sched_wakeup(data.cpu, data.time, data.pid, te); 511 sched_wakeup(sample->cpu, sample->time, sample->pid, te);
512 512
513 if (strcmp(event_str, "sched:sched_switch") == 0) 513 if (strcmp(event_str, "sched:sched_switch") == 0)
514 sched_switch(data.cpu, data.time, te); 514 sched_switch(sample->cpu, sample->time, te);
515 } 515 }
516 return 0; 516 return 0;
517} 517}
@@ -989,6 +989,9 @@ static int __cmd_record(int argc, const char **argv)
989 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 989 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
990 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 990 rec_argv = calloc(rec_argc + 1, sizeof(char *));
991 991
992 if (rec_argv == NULL)
993 return -ENOMEM;
994
992 for (i = 0; i < ARRAY_SIZE(record_args); i++) 995 for (i = 0; i < ARRAY_SIZE(record_args); i++)
993 rec_argv[i] = strdup(record_args[i]); 996 rec_argv[i] = strdup(record_args[i]);
994 997
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 3d2b47d5121a..0515ce9d3d3e 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -977,12 +977,12 @@ static int symbol_filter(struct map *map, struct symbol *sym)
977} 977}
978 978
979static void event__process_sample(const event_t *self, 979static void event__process_sample(const event_t *self,
980 struct perf_session *session, int counter) 980 struct sample_data *sample,
981 struct perf_session *session, int counter)
981{ 982{
982 u64 ip = self->ip.ip; 983 u64 ip = self->ip.ip;
983 struct sym_entry *syme; 984 struct sym_entry *syme;
984 struct addr_location al; 985 struct addr_location al;
985 struct sample_data data;
986 struct machine *machine; 986 struct machine *machine;
987 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 987 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
988 988
@@ -1025,7 +1025,7 @@ static void event__process_sample(const event_t *self,
1025 if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) 1025 if (self->header.misc & PERF_RECORD_MISC_EXACT_IP)
1026 exact_samples++; 1026 exact_samples++;
1027 1027
1028 if (event__preprocess_sample(self, session, &al, &data, 1028 if (event__preprocess_sample(self, session, &al, sample,
1029 symbol_filter) < 0 || 1029 symbol_filter) < 0 ||
1030 al.filtered) 1030 al.filtered)
1031 return; 1031 return;
@@ -1105,6 +1105,7 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
1105 unsigned int head = mmap_read_head(md); 1105 unsigned int head = mmap_read_head(md);
1106 unsigned int old = md->prev; 1106 unsigned int old = md->prev;
1107 unsigned char *data = md->base + page_size; 1107 unsigned char *data = md->base + page_size;
1108 struct sample_data sample;
1108 int diff; 1109 int diff;
1109 1110
1110 /* 1111 /*
@@ -1152,10 +1153,11 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
1152 event = &event_copy; 1153 event = &event_copy;
1153 } 1154 }
1154 1155
1156 event__parse_sample(event, self, &sample);
1155 if (event->header.type == PERF_RECORD_SAMPLE) 1157 if (event->header.type == PERF_RECORD_SAMPLE)
1156 event__process_sample(event, self, md->counter); 1158 event__process_sample(event, &sample, self, md->counter);
1157 else 1159 else
1158 event__process(event, self); 1160 event__process(event, &sample, self);
1159 old += size; 1161 old += size;
1160 } 1162 }
1161 1163
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index e437edb72417..deffb8c96071 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -14,7 +14,9 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include "debug.h" 15#include "debug.h"
16 16
17static int build_id__mark_dso_hit(event_t *event, struct perf_session *session) 17static int build_id__mark_dso_hit(event_t *event,
18 struct sample_data *sample __used,
19 struct perf_session *session)
18{ 20{
19 struct addr_location al; 21 struct addr_location al;
20 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 22 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
@@ -35,7 +37,8 @@ static int build_id__mark_dso_hit(event_t *event, struct perf_session *session)
35 return 0; 37 return 0;
36} 38}
37 39
38static int event__exit_del_thread(event_t *self, struct perf_session *session) 40static int event__exit_del_thread(event_t *self, struct sample_data *sample __used,
41 struct perf_session *session)
39{ 42{
40 struct thread *thread = perf_session__findnew(session, self->fork.tid); 43 struct thread *thread = perf_session__findnew(session, self->fork.tid);
41 44
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 7260db75b93d..e4cdc1ebe0fb 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -24,11 +24,19 @@ const char *event__name[] = {
24 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", 24 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID",
25}; 25};
26 26
27static pid_t event__synthesize_comm(pid_t pid, int full, 27static struct sample_data synth_sample = {
28 .pid = -1,
29 .tid = -1,
30 .time = -1,
31 .stream_id = -1,
32 .cpu = -1,
33 .period = 1,
34};
35
36static pid_t event__synthesize_comm(event_t *event, pid_t pid, int full,
28 event__handler_t process, 37 event__handler_t process,
29 struct perf_session *session) 38 struct perf_session *session)
30{ 39{
31 event_t ev;
32 char filename[PATH_MAX]; 40 char filename[PATH_MAX];
33 char bf[BUFSIZ]; 41 char bf[BUFSIZ];
34 FILE *fp; 42 FILE *fp;
@@ -49,34 +57,39 @@ out_race:
49 return 0; 57 return 0;
50 } 58 }
51 59
52 memset(&ev.comm, 0, sizeof(ev.comm)); 60 memset(&event->comm, 0, sizeof(event->comm));
53 while (!ev.comm.comm[0] || !ev.comm.pid) { 61
54 if (fgets(bf, sizeof(bf), fp) == NULL) 62 while (!event->comm.comm[0] || !event->comm.pid) {
55 goto out_failure; 63 if (fgets(bf, sizeof(bf), fp) == NULL) {
64 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
65 goto out;
66 }
56 67
57 if (memcmp(bf, "Name:", 5) == 0) { 68 if (memcmp(bf, "Name:", 5) == 0) {
58 char *name = bf + 5; 69 char *name = bf + 5;
59 while (*name && isspace(*name)) 70 while (*name && isspace(*name))
60 ++name; 71 ++name;
61 size = strlen(name) - 1; 72 size = strlen(name) - 1;
62 memcpy(ev.comm.comm, name, size++); 73 memcpy(event->comm.comm, name, size++);
63 } else if (memcmp(bf, "Tgid:", 5) == 0) { 74 } else if (memcmp(bf, "Tgid:", 5) == 0) {
64 char *tgids = bf + 5; 75 char *tgids = bf + 5;
65 while (*tgids && isspace(*tgids)) 76 while (*tgids && isspace(*tgids))
66 ++tgids; 77 ++tgids;
67 tgid = ev.comm.pid = atoi(tgids); 78 tgid = event->comm.pid = atoi(tgids);
68 } 79 }
69 } 80 }
70 81
71 ev.comm.header.type = PERF_RECORD_COMM; 82 event->comm.header.type = PERF_RECORD_COMM;
72 size = ALIGN(size, sizeof(u64)); 83 size = ALIGN(size, sizeof(u64));
73 ev.comm.header.size = sizeof(ev.comm) - (sizeof(ev.comm.comm) - size); 84 memset(event->comm.comm + size, 0, session->id_hdr_size);
74 85 event->comm.header.size = (sizeof(event->comm) -
86 (sizeof(event->comm.comm) - size) +
87 session->id_hdr_size);
75 if (!full) { 88 if (!full) {
76 ev.comm.tid = pid; 89 event->comm.tid = pid;
77 90
78 process(&ev, session); 91 process(event, &synth_sample, session);
79 goto out_fclose; 92 goto out;
80 } 93 }
81 94
82 snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 95 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
@@ -91,22 +104,19 @@ out_race:
91 if (*end) 104 if (*end)
92 continue; 105 continue;
93 106
94 ev.comm.tid = pid; 107 event->comm.tid = pid;
95 108
96 process(&ev, session); 109 process(event, &synth_sample, session);
97 } 110 }
98 closedir(tasks);
99 111
100out_fclose: 112 closedir(tasks);
113out:
101 fclose(fp); 114 fclose(fp);
102 return tgid;
103 115
104out_failure: 116 return tgid;
105 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
106 return -1;
107} 117}
108 118
109static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, 119static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid,
110 event__handler_t process, 120 event__handler_t process,
111 struct perf_session *session) 121 struct perf_session *session)
112{ 122{
@@ -124,29 +134,25 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
124 return -1; 134 return -1;
125 } 135 }
126 136
137 event->header.type = PERF_RECORD_MMAP;
138 /*
139 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
140 */
141 event->header.misc = PERF_RECORD_MISC_USER;
142
127 while (1) { 143 while (1) {
128 char bf[BUFSIZ], *pbf = bf; 144 char bf[BUFSIZ], *pbf = bf;
129 event_t ev = {
130 .header = {
131 .type = PERF_RECORD_MMAP,
132 /*
133 * Just like the kernel, see __perf_event_mmap
134 * in kernel/perf_event.c
135 */
136 .misc = PERF_RECORD_MISC_USER,
137 },
138 };
139 int n; 145 int n;
140 size_t size; 146 size_t size;
141 if (fgets(bf, sizeof(bf), fp) == NULL) 147 if (fgets(bf, sizeof(bf), fp) == NULL)
142 break; 148 break;
143 149
144 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ 150 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
145 n = hex2u64(pbf, &ev.mmap.start); 151 n = hex2u64(pbf, &event->mmap.start);
146 if (n < 0) 152 if (n < 0)
147 continue; 153 continue;
148 pbf += n + 1; 154 pbf += n + 1;
149 n = hex2u64(pbf, &ev.mmap.len); 155 n = hex2u64(pbf, &event->mmap.len);
150 if (n < 0) 156 if (n < 0)
151 continue; 157 continue;
152 pbf += n + 3; 158 pbf += n + 3;
@@ -161,19 +167,21 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
161 continue; 167 continue;
162 168
163 pbf += 3; 169 pbf += 3;
164 n = hex2u64(pbf, &ev.mmap.pgoff); 170 n = hex2u64(pbf, &event->mmap.pgoff);
165 171
166 size = strlen(execname); 172 size = strlen(execname);
167 execname[size - 1] = '\0'; /* Remove \n */ 173 execname[size - 1] = '\0'; /* Remove \n */
168 memcpy(ev.mmap.filename, execname, size); 174 memcpy(event->mmap.filename, execname, size);
169 size = ALIGN(size, sizeof(u64)); 175 size = ALIGN(size, sizeof(u64));
170 ev.mmap.len -= ev.mmap.start; 176 event->mmap.len -= event->mmap.start;
171 ev.mmap.header.size = (sizeof(ev.mmap) - 177 event->mmap.header.size = (sizeof(event->mmap) -
172 (sizeof(ev.mmap.filename) - size)); 178 (sizeof(event->mmap.filename) - size));
173 ev.mmap.pid = tgid; 179 memset(event->mmap.filename + size, 0, session->id_hdr_size);
174 ev.mmap.tid = pid; 180 event->mmap.header.size += session->id_hdr_size;
175 181 event->mmap.pid = tgid;
176 process(&ev, session); 182 event->mmap.tid = pid;
183
184 process(event, &synth_sample, session);
177 } 185 }
178 } 186 }
179 187
@@ -187,20 +195,27 @@ int event__synthesize_modules(event__handler_t process,
187{ 195{
188 struct rb_node *nd; 196 struct rb_node *nd;
189 struct map_groups *kmaps = &machine->kmaps; 197 struct map_groups *kmaps = &machine->kmaps;
190 u16 misc; 198 event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
199
200 if (event == NULL) {
201 pr_debug("Not enough memory synthesizing mmap event "
202 "for kernel modules\n");
203 return -1;
204 }
205
206 event->header.type = PERF_RECORD_MMAP;
191 207
192 /* 208 /*
193 * kernel uses 0 for user space maps, see kernel/perf_event.c 209 * kernel uses 0 for user space maps, see kernel/perf_event.c
194 * __perf_event_mmap 210 * __perf_event_mmap
195 */ 211 */
196 if (machine__is_host(machine)) 212 if (machine__is_host(machine))
197 misc = PERF_RECORD_MISC_KERNEL; 213 event->header.misc = PERF_RECORD_MISC_KERNEL;
198 else 214 else
199 misc = PERF_RECORD_MISC_GUEST_KERNEL; 215 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
200 216
201 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); 217 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]);
202 nd; nd = rb_next(nd)) { 218 nd; nd = rb_next(nd)) {
203 event_t ev;
204 size_t size; 219 size_t size;
205 struct map *pos = rb_entry(nd, struct map, rb_node); 220 struct map *pos = rb_entry(nd, struct map, rb_node);
206 221
@@ -208,39 +223,78 @@ int event__synthesize_modules(event__handler_t process,
208 continue; 223 continue;
209 224
210 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 225 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
211 memset(&ev, 0, sizeof(ev)); 226 event->mmap.header.type = PERF_RECORD_MMAP;
212 ev.mmap.header.misc = misc; 227 event->mmap.header.size = (sizeof(event->mmap) -
213 ev.mmap.header.type = PERF_RECORD_MMAP; 228 (sizeof(event->mmap.filename) - size));
214 ev.mmap.header.size = (sizeof(ev.mmap) - 229 memset(event->mmap.filename + size, 0, session->id_hdr_size);
215 (sizeof(ev.mmap.filename) - size)); 230 event->mmap.header.size += session->id_hdr_size;
216 ev.mmap.start = pos->start; 231 event->mmap.start = pos->start;
217 ev.mmap.len = pos->end - pos->start; 232 event->mmap.len = pos->end - pos->start;
218 ev.mmap.pid = machine->pid; 233 event->mmap.pid = machine->pid;
219 234
220 memcpy(ev.mmap.filename, pos->dso->long_name, 235 memcpy(event->mmap.filename, pos->dso->long_name,
221 pos->dso->long_name_len + 1); 236 pos->dso->long_name_len + 1);
222 process(&ev, session); 237 process(event, &synth_sample, session);
223 } 238 }
224 239
240 free(event);
225 return 0; 241 return 0;
226} 242}
227 243
228int event__synthesize_thread(pid_t pid, event__handler_t process, 244static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event,
229 struct perf_session *session) 245 pid_t pid, event__handler_t process,
246 struct perf_session *session)
230{ 247{
231 pid_t tgid = event__synthesize_comm(pid, 1, process, session); 248 pid_t tgid = event__synthesize_comm(comm_event, pid, 1, process,
249 session);
232 if (tgid == -1) 250 if (tgid == -1)
233 return -1; 251 return -1;
234 return event__synthesize_mmap_events(pid, tgid, process, session); 252 return event__synthesize_mmap_events(mmap_event, pid, tgid,
253 process, session);
254}
255
256int event__synthesize_thread(pid_t pid, event__handler_t process,
257 struct perf_session *session)
258{
259 event_t *comm_event, *mmap_event;
260 int err = -1;
261
262 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
263 if (comm_event == NULL)
264 goto out;
265
266 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
267 if (mmap_event == NULL)
268 goto out_free_comm;
269
270 err = __event__synthesize_thread(comm_event, mmap_event, pid,
271 process, session);
272 free(mmap_event);
273out_free_comm:
274 free(comm_event);
275out:
276 return err;
235} 277}
236 278
237void event__synthesize_threads(event__handler_t process, 279int event__synthesize_threads(event__handler_t process,
238 struct perf_session *session) 280 struct perf_session *session)
239{ 281{
240 DIR *proc; 282 DIR *proc;
241 struct dirent dirent, *next; 283 struct dirent dirent, *next;
284 event_t *comm_event, *mmap_event;
285 int err = -1;
286
287 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
288 if (comm_event == NULL)
289 goto out;
290
291 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
292 if (mmap_event == NULL)
293 goto out_free_comm;
242 294
243 proc = opendir("/proc"); 295 proc = opendir("/proc");
296 if (proc == NULL)
297 goto out_free_mmap;
244 298
245 while (!readdir_r(proc, &dirent, &next) && next) { 299 while (!readdir_r(proc, &dirent, &next) && next) {
246 char *end; 300 char *end;
@@ -249,10 +303,18 @@ void event__synthesize_threads(event__handler_t process,
249 if (*end) /* only interested in proper numerical dirents */ 303 if (*end) /* only interested in proper numerical dirents */
250 continue; 304 continue;
251 305
252 event__synthesize_thread(pid, process, session); 306 __event__synthesize_thread(comm_event, mmap_event, pid,
307 process, session);
253 } 308 }
254 309
255 closedir(proc); 310 closedir(proc);
311 err = 0;
312out_free_mmap:
313 free(mmap_event);
314out_free_comm:
315 free(comm_event);
316out:
317 return err;
256} 318}
257 319
258struct process_symbol_args { 320struct process_symbol_args {
@@ -286,18 +348,20 @@ int event__synthesize_kernel_mmap(event__handler_t process,
286 char path[PATH_MAX]; 348 char path[PATH_MAX];
287 char name_buff[PATH_MAX]; 349 char name_buff[PATH_MAX];
288 struct map *map; 350 struct map *map;
289 351 int err;
290 event_t ev = {
291 .header = {
292 .type = PERF_RECORD_MMAP,
293 },
294 };
295 /* 352 /*
296 * We should get this from /sys/kernel/sections/.text, but till that is 353 * We should get this from /sys/kernel/sections/.text, but till that is
297 * available use this, and after it is use this as a fallback for older 354 * available use this, and after it is use this as a fallback for older
298 * kernels. 355 * kernels.
299 */ 356 */
300 struct process_symbol_args args = { .name = symbol_name, }; 357 struct process_symbol_args args = { .name = symbol_name, };
358 event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
359
360 if (event == NULL) {
361 pr_debug("Not enough memory synthesizing mmap event "
362 "for kernel modules\n");
363 return -1;
364 }
301 365
302 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); 366 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
303 if (machine__is_host(machine)) { 367 if (machine__is_host(machine)) {
@@ -305,10 +369,10 @@ int event__synthesize_kernel_mmap(event__handler_t process,
305 * kernel uses PERF_RECORD_MISC_USER for user space maps, 369 * kernel uses PERF_RECORD_MISC_USER for user space maps,
306 * see kernel/perf_event.c __perf_event_mmap 370 * see kernel/perf_event.c __perf_event_mmap
307 */ 371 */
308 ev.header.misc = PERF_RECORD_MISC_KERNEL; 372 event->header.misc = PERF_RECORD_MISC_KERNEL;
309 filename = "/proc/kallsyms"; 373 filename = "/proc/kallsyms";
310 } else { 374 } else {
311 ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 375 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
312 if (machine__is_default_guest(machine)) 376 if (machine__is_default_guest(machine))
313 filename = (char *) symbol_conf.default_guest_kallsyms; 377 filename = (char *) symbol_conf.default_guest_kallsyms;
314 else { 378 else {
@@ -321,17 +385,21 @@ int event__synthesize_kernel_mmap(event__handler_t process,
321 return -ENOENT; 385 return -ENOENT;
322 386
323 map = machine->vmlinux_maps[MAP__FUNCTION]; 387 map = machine->vmlinux_maps[MAP__FUNCTION];
324 size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), 388 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
325 "%s%s", mmap_name, symbol_name) + 1; 389 "%s%s", mmap_name, symbol_name) + 1;
326 size = ALIGN(size, sizeof(u64)); 390 size = ALIGN(size, sizeof(u64));
327 ev.mmap.header.size = (sizeof(ev.mmap) - 391 event->mmap.header.type = PERF_RECORD_MMAP;
328 (sizeof(ev.mmap.filename) - size)); 392 event->mmap.header.size = (sizeof(event->mmap) -
329 ev.mmap.pgoff = args.start; 393 (sizeof(event->mmap.filename) - size) + session->id_hdr_size);
330 ev.mmap.start = map->start; 394 event->mmap.pgoff = args.start;
331 ev.mmap.len = map->end - ev.mmap.start; 395 event->mmap.start = map->start;
332 ev.mmap.pid = machine->pid; 396 event->mmap.len = map->end - event->mmap.start;
333 397 event->mmap.pid = machine->pid;
334 return process(&ev, session); 398
399 err = process(event, &synth_sample, session);
400 free(event);
401
402 return err;
335} 403}
336 404
337static void thread__comm_adjust(struct thread *self, struct hists *hists) 405static void thread__comm_adjust(struct thread *self, struct hists *hists)
@@ -361,7 +429,8 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm,
361 return 0; 429 return 0;
362} 430}
363 431
364int event__process_comm(event_t *self, struct perf_session *session) 432int event__process_comm(event_t *self, struct sample_data *sample __used,
433 struct perf_session *session)
365{ 434{
366 struct thread *thread = perf_session__findnew(session, self->comm.tid); 435 struct thread *thread = perf_session__findnew(session, self->comm.tid);
367 436
@@ -376,7 +445,8 @@ int event__process_comm(event_t *self, struct perf_session *session)
376 return 0; 445 return 0;
377} 446}
378 447
379int event__process_lost(event_t *self, struct perf_session *session) 448int event__process_lost(event_t *self, struct sample_data *sample __used,
449 struct perf_session *session)
380{ 450{
381 dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); 451 dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost);
382 session->hists.stats.total_lost += self->lost.lost; 452 session->hists.stats.total_lost += self->lost.lost;
@@ -485,7 +555,8 @@ out_problem:
485 return -1; 555 return -1;
486} 556}
487 557
488int event__process_mmap(event_t *self, struct perf_session *session) 558int event__process_mmap(event_t *self, struct sample_data *sample __used,
559 struct perf_session *session)
489{ 560{
490 struct machine *machine; 561 struct machine *machine;
491 struct thread *thread; 562 struct thread *thread;
@@ -526,7 +597,8 @@ out_problem:
526 return 0; 597 return 0;
527} 598}
528 599
529int event__process_task(event_t *self, struct perf_session *session) 600int event__process_task(event_t *self, struct sample_data *sample __used,
601 struct perf_session *session)
530{ 602{
531 struct thread *thread = perf_session__findnew(session, self->fork.tid); 603 struct thread *thread = perf_session__findnew(session, self->fork.tid);
532 struct thread *parent = perf_session__findnew(session, self->fork.ptid); 604 struct thread *parent = perf_session__findnew(session, self->fork.ptid);
@@ -548,18 +620,19 @@ int event__process_task(event_t *self, struct perf_session *session)
548 return 0; 620 return 0;
549} 621}
550 622
551int event__process(event_t *event, struct perf_session *session) 623int event__process(event_t *event, struct sample_data *sample,
624 struct perf_session *session)
552{ 625{
553 switch (event->header.type) { 626 switch (event->header.type) {
554 case PERF_RECORD_COMM: 627 case PERF_RECORD_COMM:
555 event__process_comm(event, session); 628 event__process_comm(event, sample, session);
556 break; 629 break;
557 case PERF_RECORD_MMAP: 630 case PERF_RECORD_MMAP:
558 event__process_mmap(event, session); 631 event__process_mmap(event, sample, session);
559 break; 632 break;
560 case PERF_RECORD_FORK: 633 case PERF_RECORD_FORK:
561 case PERF_RECORD_EXIT: 634 case PERF_RECORD_EXIT:
562 event__process_task(event, session); 635 event__process_task(event, sample, session);
563 break; 636 break;
564 default: 637 default:
565 break; 638 break;
@@ -674,32 +747,8 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
674 symbol_filter_t filter) 747 symbol_filter_t filter)
675{ 748{
676 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 749 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
677 struct thread *thread; 750 struct thread *thread = perf_session__findnew(session, self->ip.pid);
678
679 event__parse_sample(self, session->sample_type, data);
680 751
681 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld cpu:%d\n",
682 self->header.misc, data->pid, data->tid, data->ip,
683 data->period, data->cpu);
684
685 if (session->sample_type & PERF_SAMPLE_CALLCHAIN) {
686 unsigned int i;
687
688 dump_printf("... chain: nr:%Lu\n", data->callchain->nr);
689
690 if (!ip_callchain__valid(data->callchain, self)) {
691 pr_debug("call-chain problem with event, "
692 "skipping it.\n");
693 goto out_filtered;
694 }
695
696 if (dump_trace) {
697 for (i = 0; i < data->callchain->nr; i++)
698 dump_printf("..... %2d: %016Lx\n",
699 i, data->callchain->ips[i]);
700 }
701 }
702 thread = perf_session__findnew(session, self->ip.pid);
703 if (thread == NULL) 752 if (thread == NULL)
704 return -1; 753 return -1;
705 754
@@ -766,9 +815,65 @@ out_filtered:
766 return 0; 815 return 0;
767} 816}
768 817
769int event__parse_sample(const event_t *event, u64 type, struct sample_data *data) 818static int event__parse_id_sample(const event_t *event,
819 struct perf_session *session,
820 struct sample_data *sample)
770{ 821{
771 const u64 *array = event->sample.array; 822 const u64 *array;
823 u64 type;
824
825 sample->cpu = sample->pid = sample->tid = -1;
826 sample->stream_id = sample->id = sample->time = -1ULL;
827
828 if (!session->sample_id_all)
829 return 0;
830
831 array = event->sample.array;
832 array += ((event->header.size -
833 sizeof(event->header)) / sizeof(u64)) - 1;
834 type = session->sample_type;
835
836 if (type & PERF_SAMPLE_CPU) {
837 u32 *p = (u32 *)array;
838 sample->cpu = *p;
839 array--;
840 }
841
842 if (type & PERF_SAMPLE_STREAM_ID) {
843 sample->stream_id = *array;
844 array--;
845 }
846
847 if (type & PERF_SAMPLE_ID) {
848 sample->id = *array;
849 array--;
850 }
851
852 if (type & PERF_SAMPLE_TIME) {
853 sample->time = *array;
854 array--;
855 }
856
857 if (type & PERF_SAMPLE_TID) {
858 u32 *p = (u32 *)array;
859 sample->pid = p[0];
860 sample->tid = p[1];
861 }
862
863 return 0;
864}
865
866int event__parse_sample(const event_t *event, struct perf_session *session,
867 struct sample_data *data)
868{
869 const u64 *array;
870 u64 type;
871
872 if (event->header.type != PERF_RECORD_SAMPLE)
873 return event__parse_id_sample(event, session, data);
874
875 array = event->sample.array;
876 type = session->sample_type;
772 877
773 if (type & PERF_SAMPLE_IP) { 878 if (type & PERF_SAMPLE_IP) {
774 data->ip = event->ip.ip; 879 data->ip = event->ip.ip;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 8e790dae7026..a95ab18575ce 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -135,12 +135,15 @@ void event__print_totals(void);
135 135
136struct perf_session; 136struct perf_session;
137 137
138typedef int (*event__handler_t)(event_t *event, struct perf_session *session); 138typedef int (*event__handler_synth_t)(event_t *event,
139 struct perf_session *session);
140typedef int (*event__handler_t)(event_t *event, struct sample_data *sample,
141 struct perf_session *session);
139 142
140int event__synthesize_thread(pid_t pid, event__handler_t process, 143int event__synthesize_thread(pid_t pid, event__handler_t process,
141 struct perf_session *session); 144 struct perf_session *session);
142void event__synthesize_threads(event__handler_t process, 145int event__synthesize_threads(event__handler_t process,
143 struct perf_session *session); 146 struct perf_session *session);
144int event__synthesize_kernel_mmap(event__handler_t process, 147int event__synthesize_kernel_mmap(event__handler_t process,
145 struct perf_session *session, 148 struct perf_session *session,
146 struct machine *machine, 149 struct machine *machine,
@@ -150,17 +153,23 @@ int event__synthesize_modules(event__handler_t process,
150 struct perf_session *session, 153 struct perf_session *session,
151 struct machine *machine); 154 struct machine *machine);
152 155
153int event__process_comm(event_t *self, struct perf_session *session); 156int event__process_comm(event_t *self, struct sample_data *sample,
154int event__process_lost(event_t *self, struct perf_session *session); 157 struct perf_session *session);
155int event__process_mmap(event_t *self, struct perf_session *session); 158int event__process_lost(event_t *self, struct sample_data *sample,
156int event__process_task(event_t *self, struct perf_session *session); 159 struct perf_session *session);
157int event__process(event_t *event, struct perf_session *session); 160int event__process_mmap(event_t *self, struct sample_data *sample,
161 struct perf_session *session);
162int event__process_task(event_t *self, struct sample_data *sample,
163 struct perf_session *session);
164int event__process(event_t *event, struct sample_data *sample,
165 struct perf_session *session);
158 166
159struct addr_location; 167struct addr_location;
160int event__preprocess_sample(const event_t *self, struct perf_session *session, 168int event__preprocess_sample(const event_t *self, struct perf_session *session,
161 struct addr_location *al, struct sample_data *data, 169 struct addr_location *al, struct sample_data *data,
162 symbol_filter_t filter); 170 symbol_filter_t filter);
163int event__parse_sample(const event_t *event, u64 type, struct sample_data *data); 171int event__parse_sample(const event_t *event, struct perf_session *session,
172 struct sample_data *sample);
164 173
165extern const char *event__name[]; 174extern const char *event__name[];
166 175
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index f65d7dc127b6..76e949a59ea4 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -946,6 +946,24 @@ u64 perf_header__sample_type(struct perf_header *header)
946 return type; 946 return type;
947} 947}
948 948
949bool perf_header__sample_id_all(const struct perf_header *header)
950{
951 bool value = false, first = true;
952 int i;
953
954 for (i = 0; i < header->attrs; i++) {
955 struct perf_header_attr *attr = header->attr[i];
956
957 if (first) {
958 value = attr->attr.sample_id_all;
959 first = false;
960 } else if (value != attr->attr.sample_id_all)
961 die("non matching sample_id_all");
962 }
963
964 return value;
965}
966
949struct perf_event_attr * 967struct perf_event_attr *
950perf_header__find_attr(u64 id, struct perf_header *header) 968perf_header__find_attr(u64 id, struct perf_header *header)
951{ 969{
@@ -987,21 +1005,23 @@ int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
987 1005
988 ev = malloc(size); 1006 ev = malloc(size);
989 1007
1008 if (ev == NULL)
1009 return -ENOMEM;
1010
990 ev->attr.attr = *attr; 1011 ev->attr.attr = *attr;
991 memcpy(ev->attr.id, id, ids * sizeof(u64)); 1012 memcpy(ev->attr.id, id, ids * sizeof(u64));
992 1013
993 ev->attr.header.type = PERF_RECORD_HEADER_ATTR; 1014 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
994 ev->attr.header.size = size; 1015 ev->attr.header.size = size;
995 1016
996 err = process(ev, session); 1017 err = process(ev, NULL, session);
997 1018
998 free(ev); 1019 free(ev);
999 1020
1000 return err; 1021 return err;
1001} 1022}
1002 1023
1003int event__synthesize_attrs(struct perf_header *self, 1024int event__synthesize_attrs(struct perf_header *self, event__handler_t process,
1004 event__handler_t process,
1005 struct perf_session *session) 1025 struct perf_session *session)
1006{ 1026{
1007 struct perf_header_attr *attr; 1027 struct perf_header_attr *attr;
@@ -1071,7 +1091,7 @@ int event__synthesize_event_type(u64 event_id, char *name,
1071 ev.event_type.header.size = sizeof(ev.event_type) - 1091 ev.event_type.header.size = sizeof(ev.event_type) -
1072 (sizeof(ev.event_type.event_type.name) - size); 1092 (sizeof(ev.event_type.event_type.name) - size);
1073 1093
1074 err = process(&ev, session); 1094 err = process(&ev, NULL, session);
1075 1095
1076 return err; 1096 return err;
1077} 1097}
@@ -1126,7 +1146,7 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
1126 ev.tracing_data.header.size = sizeof(ev.tracing_data); 1146 ev.tracing_data.header.size = sizeof(ev.tracing_data);
1127 ev.tracing_data.size = aligned_size; 1147 ev.tracing_data.size = aligned_size;
1128 1148
1129 process(&ev, session); 1149 process(&ev, NULL, session);
1130 1150
1131 err = read_tracing_data(fd, pattrs, nb_events); 1151 err = read_tracing_data(fd, pattrs, nb_events);
1132 write_padded(fd, NULL, 0, padding); 1152 write_padded(fd, NULL, 0, padding);
@@ -1186,7 +1206,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc,
1186 ev.build_id.header.size = sizeof(ev.build_id) + len; 1206 ev.build_id.header.size = sizeof(ev.build_id) + len;
1187 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); 1207 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
1188 1208
1189 err = process(&ev, session); 1209 err = process(&ev, NULL, session);
1190 1210
1191 return err; 1211 return err;
1192} 1212}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index ed550bffd655..6335965e1f93 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -81,6 +81,7 @@ void perf_header_attr__delete(struct perf_header_attr *self);
81int perf_header_attr__add_id(struct perf_header_attr *self, u64 id); 81int perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
82 82
83u64 perf_header__sample_type(struct perf_header *header); 83u64 perf_header__sample_type(struct perf_header *header);
84bool perf_header__sample_id_all(const struct perf_header *header);
84struct perf_event_attr * 85struct perf_event_attr *
85perf_header__find_attr(u64 id, struct perf_header *header); 86perf_header__find_attr(u64 id, struct perf_header *header);
86void perf_header__set_feat(struct perf_header *self, int feat); 87void perf_header__set_feat(struct perf_header *self, int feat);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 587d375d3430..ee789856a8c9 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -52,8 +52,10 @@ struct sym_priv {
52struct events_stats { 52struct events_stats {
53 u64 total_period; 53 u64 total_period;
54 u64 total_lost; 54 u64 total_lost;
55 u64 total_invalid_chains;
55 u32 nr_events[PERF_RECORD_HEADER_MAX]; 56 u32 nr_events[PERF_RECORD_HEADER_MAX];
56 u32 nr_unknown_events; 57 u32 nr_unknown_events;
58 u32 nr_invalid_chains;
57}; 59};
58 60
59enum hist_column { 61enum hist_column {
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index c7d72dce54b2..abc31a1dac1a 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -119,6 +119,10 @@ struct option {
119 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG } 119 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG }
120#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \ 120#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
121 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT } 121 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
122#define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \
123 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\
124 .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\
125 .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG}
122 126
123/* parse_options() will filter out the processed options and leave the 127/* parse_options() will filter out the processed options and leave the
124 * non-option argments in argv[]. 128 * non-option argments in argv[].
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 52672dad1fe9..3074d38897e6 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -65,9 +65,49 @@ out_close:
65 return -1; 65 return -1;
66} 66}
67 67
68static void perf_session__id_header_size(struct perf_session *session)
69{
70 struct sample_data *data;
71 u64 sample_type = session->sample_type;
72 u16 size = 0;
73
74 if (!session->sample_id_all)
75 goto out;
76
77 if (sample_type & PERF_SAMPLE_TID)
78 size += sizeof(data->tid) * 2;
79
80 if (sample_type & PERF_SAMPLE_TIME)
81 size += sizeof(data->time);
82
83 if (sample_type & PERF_SAMPLE_ID)
84 size += sizeof(data->id);
85
86 if (sample_type & PERF_SAMPLE_STREAM_ID)
87 size += sizeof(data->stream_id);
88
89 if (sample_type & PERF_SAMPLE_CPU)
90 size += sizeof(data->cpu) * 2;
91out:
92 session->id_hdr_size = size;
93}
94
95void perf_session__set_sample_id_all(struct perf_session *session, bool value)
96{
97 session->sample_id_all = value;
98 perf_session__id_header_size(session);
99}
100
101void perf_session__set_sample_type(struct perf_session *session, u64 type)
102{
103 session->sample_type = type;
104}
105
68void perf_session__update_sample_type(struct perf_session *self) 106void perf_session__update_sample_type(struct perf_session *self)
69{ 107{
70 self->sample_type = perf_header__sample_type(&self->header); 108 self->sample_type = perf_header__sample_type(&self->header);
109 self->sample_id_all = perf_header__sample_id_all(&self->header);
110 perf_session__id_header_size(self);
71} 111}
72 112
73int perf_session__create_kernel_maps(struct perf_session *self) 113int perf_session__create_kernel_maps(struct perf_session *self)
@@ -240,7 +280,15 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
240 return syms; 280 return syms;
241} 281}
242 282
283static int process_event_synth_stub(event_t *event __used,
284 struct perf_session *session __used)
285{
286 dump_printf(": unhandled!\n");
287 return 0;
288}
289
243static int process_event_stub(event_t *event __used, 290static int process_event_stub(event_t *event __used,
291 struct sample_data *sample __used,
244 struct perf_session *session __used) 292 struct perf_session *session __used)
245{ 293{
246 dump_printf(": unhandled!\n"); 294 dump_printf(": unhandled!\n");
@@ -280,13 +328,13 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
280 if (handler->unthrottle == NULL) 328 if (handler->unthrottle == NULL)
281 handler->unthrottle = process_event_stub; 329 handler->unthrottle = process_event_stub;
282 if (handler->attr == NULL) 330 if (handler->attr == NULL)
283 handler->attr = process_event_stub; 331 handler->attr = process_event_synth_stub;
284 if (handler->event_type == NULL) 332 if (handler->event_type == NULL)
285 handler->event_type = process_event_stub; 333 handler->event_type = process_event_synth_stub;
286 if (handler->tracing_data == NULL) 334 if (handler->tracing_data == NULL)
287 handler->tracing_data = process_event_stub; 335 handler->tracing_data = process_event_synth_stub;
288 if (handler->build_id == NULL) 336 if (handler->build_id == NULL)
289 handler->build_id = process_event_stub; 337 handler->build_id = process_event_synth_stub;
290 if (handler->finished_round == NULL) { 338 if (handler->finished_round == NULL) {
291 if (handler->ordered_samples) 339 if (handler->ordered_samples)
292 handler->finished_round = process_finished_round; 340 handler->finished_round = process_finished_round;
@@ -413,12 +461,18 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
413 } 461 }
414} 462}
415 463
464static int perf_session_deliver_event(struct perf_session *session,
465 event_t *event,
466 struct sample_data *sample,
467 struct perf_event_ops *ops);
468
416static void flush_sample_queue(struct perf_session *s, 469static void flush_sample_queue(struct perf_session *s,
417 struct perf_event_ops *ops) 470 struct perf_event_ops *ops)
418{ 471{
419 struct ordered_samples *os = &s->ordered_samples; 472 struct ordered_samples *os = &s->ordered_samples;
420 struct list_head *head = &os->samples; 473 struct list_head *head = &os->samples;
421 struct sample_queue *tmp, *iter; 474 struct sample_queue *tmp, *iter;
475 struct sample_data sample;
422 u64 limit = os->next_flush; 476 u64 limit = os->next_flush;
423 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; 477 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
424 478
@@ -429,7 +483,8 @@ static void flush_sample_queue(struct perf_session *s,
429 if (iter->timestamp > limit) 483 if (iter->timestamp > limit)
430 break; 484 break;
431 485
432 ops->sample(iter->event, s); 486 event__parse_sample(iter->event, s, &sample);
487 perf_session_deliver_event(s, iter->event, &sample, ops);
433 488
434 os->last_flush = iter->timestamp; 489 os->last_flush = iter->timestamp;
435 list_del(&iter->list); 490 list_del(&iter->list);
@@ -494,8 +549,7 @@ static int process_finished_round(event_t *event __used,
494} 549}
495 550
496/* The queue is ordered by time */ 551/* The queue is ordered by time */
497static void __queue_sample_event(struct sample_queue *new, 552static void __queue_event(struct sample_queue *new, struct perf_session *s)
498 struct perf_session *s)
499{ 553{
500 struct ordered_samples *os = &s->ordered_samples; 554 struct ordered_samples *os = &s->ordered_samples;
501 struct sample_queue *sample = os->last_sample; 555 struct sample_queue *sample = os->last_sample;
@@ -541,14 +595,17 @@ static void __queue_sample_event(struct sample_queue *new,
541 595
542#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue)) 596#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
543 597
544static int queue_sample_event(event_t *event, struct sample_data *data, 598static int perf_session_queue_event(struct perf_session *s, event_t *event,
545 struct perf_session *s) 599 struct sample_data *data)
546{ 600{
547 struct ordered_samples *os = &s->ordered_samples; 601 struct ordered_samples *os = &s->ordered_samples;
548 struct list_head *sc = &os->sample_cache; 602 struct list_head *sc = &os->sample_cache;
549 u64 timestamp = data->time; 603 u64 timestamp = data->time;
550 struct sample_queue *new; 604 struct sample_queue *new;
551 605
606 if (!timestamp)
607 return -ETIME;
608
552 if (timestamp < s->ordered_samples.last_flush) { 609 if (timestamp < s->ordered_samples.last_flush) {
553 printf("Warning: Timestamp below last timeslice flush\n"); 610 printf("Warning: Timestamp below last timeslice flush\n");
554 return -EINVAL; 611 return -EINVAL;
@@ -573,79 +630,142 @@ static int queue_sample_event(event_t *event, struct sample_data *data,
573 new->timestamp = timestamp; 630 new->timestamp = timestamp;
574 new->event = event; 631 new->event = event;
575 632
576 __queue_sample_event(new, s); 633 __queue_event(new, s);
577 634
578 return 0; 635 return 0;
579} 636}
580 637
581static int perf_session__process_sample(event_t *event, struct perf_session *s, 638static void callchain__dump(struct sample_data *sample)
582 struct perf_event_ops *ops)
583{ 639{
584 struct sample_data data; 640 unsigned int i;
585
586 if (!ops->ordered_samples)
587 return ops->sample(event, s);
588 641
589 bzero(&data, sizeof(struct sample_data)); 642 if (!dump_trace)
590 event__parse_sample(event, s->sample_type, &data); 643 return;
591 644
592 queue_sample_event(event, &data, s); 645 printf("... chain: nr:%Lu\n", sample->callchain->nr);
593 646
594 return 0; 647 for (i = 0; i < sample->callchain->nr; i++)
648 printf("..... %2d: %016Lx\n", i, sample->callchain->ips[i]);
595} 649}
596 650
597static int perf_session__process_event(struct perf_session *self, 651static void perf_session__print_tstamp(struct perf_session *session,
598 event_t *event, 652 event_t *event,
599 struct perf_event_ops *ops, 653 struct sample_data *sample)
600 u64 file_offset)
601{ 654{
602 trace_event(event); 655 if (event->header.type != PERF_RECORD_SAMPLE &&
603 656 !session->sample_id_all) {
604 if (event->header.type < PERF_RECORD_HEADER_MAX) { 657 fputs("-1 -1 ", stdout);
605 dump_printf("%#Lx [%#x]: PERF_RECORD_%s", 658 return;
606 file_offset, event->header.size,
607 event__name[event->header.type]);
608 hists__inc_nr_events(&self->hists, event->header.type);
609 } 659 }
610 660
611 if (self->header.needs_swap && event__swap_ops[event->header.type]) 661 if ((session->sample_type & PERF_SAMPLE_CPU))
612 event__swap_ops[event->header.type](event); 662 printf("%u ", sample->cpu);
613 663
664 if (session->sample_type & PERF_SAMPLE_TIME)
665 printf("%Lu ", sample->time);
666}
667
668static int perf_session_deliver_event(struct perf_session *session,
669 event_t *event,
670 struct sample_data *sample,
671 struct perf_event_ops *ops)
672{
614 switch (event->header.type) { 673 switch (event->header.type) {
615 case PERF_RECORD_SAMPLE: 674 case PERF_RECORD_SAMPLE:
616 return perf_session__process_sample(event, self, ops); 675 return ops->sample(event, sample, session);
617 case PERF_RECORD_MMAP: 676 case PERF_RECORD_MMAP:
618 return ops->mmap(event, self); 677 return ops->mmap(event, sample, session);
619 case PERF_RECORD_COMM: 678 case PERF_RECORD_COMM:
620 return ops->comm(event, self); 679 return ops->comm(event, sample, session);
621 case PERF_RECORD_FORK: 680 case PERF_RECORD_FORK:
622 return ops->fork(event, self); 681 return ops->fork(event, sample, session);
623 case PERF_RECORD_EXIT: 682 case PERF_RECORD_EXIT:
624 return ops->exit(event, self); 683 return ops->exit(event, sample, session);
625 case PERF_RECORD_LOST: 684 case PERF_RECORD_LOST:
626 return ops->lost(event, self); 685 return ops->lost(event, sample, session);
627 case PERF_RECORD_READ: 686 case PERF_RECORD_READ:
628 return ops->read(event, self); 687 return ops->read(event, sample, session);
629 case PERF_RECORD_THROTTLE: 688 case PERF_RECORD_THROTTLE:
630 return ops->throttle(event, self); 689 return ops->throttle(event, sample, session);
631 case PERF_RECORD_UNTHROTTLE: 690 case PERF_RECORD_UNTHROTTLE:
632 return ops->unthrottle(event, self); 691 return ops->unthrottle(event, sample, session);
692 default:
693 ++session->hists.stats.nr_unknown_events;
694 return -1;
695 }
696}
697
698static int perf_session__process_event(struct perf_session *session,
699 event_t *event,
700 struct perf_event_ops *ops,
701 u64 file_offset)
702{
703 struct sample_data sample;
704 int ret;
705
706 trace_event(event);
707
708 if (session->header.needs_swap && event__swap_ops[event->header.type])
709 event__swap_ops[event->header.type](event);
710
711 if (event->header.type >= PERF_RECORD_MMAP &&
712 event->header.type <= PERF_RECORD_SAMPLE) {
713 event__parse_sample(event, session, &sample);
714 if (dump_trace)
715 perf_session__print_tstamp(session, event, &sample);
716 }
717
718 if (event->header.type < PERF_RECORD_HEADER_MAX) {
719 dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
720 file_offset, event->header.size,
721 event__name[event->header.type]);
722 hists__inc_nr_events(&session->hists, event->header.type);
723 }
724
725 /* These events are processed right away */
726 switch (event->header.type) {
727 case PERF_RECORD_SAMPLE:
728 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n",
729 event->header.misc,
730 sample.pid, sample.tid, sample.ip, sample.period);
731
732 if (session->sample_type & PERF_SAMPLE_CALLCHAIN) {
733 if (!ip_callchain__valid(sample.callchain, event)) {
734 pr_debug("call-chain problem with event, "
735 "skipping it.\n");
736 ++session->hists.stats.nr_invalid_chains;
737 session->hists.stats.total_invalid_chains +=
738 sample.period;
739 return 0;
740 }
741
742 callchain__dump(&sample);
743 }
744 break;
745
633 case PERF_RECORD_HEADER_ATTR: 746 case PERF_RECORD_HEADER_ATTR:
634 return ops->attr(event, self); 747 return ops->attr(event, session);
635 case PERF_RECORD_HEADER_EVENT_TYPE: 748 case PERF_RECORD_HEADER_EVENT_TYPE:
636 return ops->event_type(event, self); 749 return ops->event_type(event, session);
637 case PERF_RECORD_HEADER_TRACING_DATA: 750 case PERF_RECORD_HEADER_TRACING_DATA:
638 /* setup for reading amidst mmap */ 751 /* setup for reading amidst mmap */
639 lseek(self->fd, file_offset, SEEK_SET); 752 lseek(session->fd, file_offset, SEEK_SET);
640 return ops->tracing_data(event, self); 753 return ops->tracing_data(event, session);
641 case PERF_RECORD_HEADER_BUILD_ID: 754 case PERF_RECORD_HEADER_BUILD_ID:
642 return ops->build_id(event, self); 755 return ops->build_id(event, session);
643 case PERF_RECORD_FINISHED_ROUND: 756 case PERF_RECORD_FINISHED_ROUND:
644 return ops->finished_round(event, self, ops); 757 return ops->finished_round(event, session, ops);
645 default: 758 default:
646 ++self->hists.stats.nr_unknown_events; 759 break;
647 return -1;
648 } 760 }
761
762 if (ops->ordered_samples) {
763 ret = perf_session_queue_event(session, event, &sample);
764 if (ret != -ETIME)
765 return ret;
766 }
767
768 return perf_session_deliver_event(session, event, &sample, ops);
649} 769}
650 770
651void perf_event_header__bswap(struct perf_event_header *self) 771void perf_event_header__bswap(struct perf_event_header *self)
@@ -894,6 +1014,14 @@ out_err:
894 session->hists.stats.nr_unknown_events); 1014 session->hists.stats.nr_unknown_events);
895 } 1015 }
896 1016
1017 if (session->hists.stats.nr_invalid_chains != 0) {
1018 ui__warning("Found invalid callchains!\n\n"
1019 "%u out of %u events were discarded for this reason.\n\n"
1020 "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
1021 session->hists.stats.nr_invalid_chains,
1022 session->hists.stats.nr_events[PERF_RECORD_SAMPLE]);
1023 }
1024
897 perf_session_free_sample_buffers(session); 1025 perf_session_free_sample_buffers(session);
898 return err; 1026 return err;
899} 1027}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 5bf6efa3788a..ac36f99f14af 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -46,6 +46,8 @@ struct perf_session {
46 int fd; 46 int fd;
47 bool fd_pipe; 47 bool fd_pipe;
48 bool repipe; 48 bool repipe;
49 bool sample_id_all;
50 u16 id_hdr_size;
49 int cwdlen; 51 int cwdlen;
50 char *cwd; 52 char *cwd;
51 struct ordered_samples ordered_samples; 53 struct ordered_samples ordered_samples;
@@ -54,7 +56,9 @@ struct perf_session {
54 56
55struct perf_event_ops; 57struct perf_event_ops;
56 58
57typedef int (*event_op)(event_t *self, struct perf_session *session); 59typedef int (*event_op)(event_t *self, struct sample_data *sample,
60 struct perf_session *session);
61typedef int (*event_synth_op)(event_t *self, struct perf_session *session);
58typedef int (*event_op2)(event_t *self, struct perf_session *session, 62typedef int (*event_op2)(event_t *self, struct perf_session *session,
59 struct perf_event_ops *ops); 63 struct perf_event_ops *ops);
60 64
@@ -67,8 +71,8 @@ struct perf_event_ops {
67 lost, 71 lost,
68 read, 72 read,
69 throttle, 73 throttle,
70 unthrottle, 74 unthrottle;
71 attr, 75 event_synth_op attr,
72 event_type, 76 event_type,
73 tracing_data, 77 tracing_data,
74 build_id; 78 build_id;
@@ -104,6 +108,8 @@ int perf_session__create_kernel_maps(struct perf_session *self);
104 108
105int do_read(int fd, void *buf, size_t size); 109int do_read(int fd, void *buf, size_t size);
106void perf_session__update_sample_type(struct perf_session *self); 110void perf_session__update_sample_type(struct perf_session *self);
111void perf_session__set_sample_id_all(struct perf_session *session, bool value);
112void perf_session__set_sample_type(struct perf_session *session, u64 type);
107void perf_session__remove_thread(struct perf_session *self, struct thread *th); 113void perf_session__remove_thread(struct perf_session *self, struct thread *th);
108 114
109static inline 115static inline
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index b62a553cc67d..f44fa541d56e 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -170,7 +170,7 @@ static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
170 return repsep_snprintf(bf, size, "%-*s", width, dso_name); 170 return repsep_snprintf(bf, size, "%-*s", width, dso_name);
171 } 171 }
172 172
173 return repsep_snprintf(bf, size, "%*Lx", width, self->ip); 173 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
174} 174}
175 175
176/* --sort symbol */ 176/* --sort symbol */
@@ -196,7 +196,7 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
196 196
197 if (verbose) { 197 if (verbose) {
198 char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!'; 198 char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!';
199 ret += repsep_snprintf(bf, size, "%*Lx %c ", 199 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
200 BITS_PER_LONG / 4, self->ip, o); 200 BITS_PER_LONG / 4, self->ip, o);
201 } 201 }
202 202
@@ -205,7 +205,7 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
205 ret += repsep_snprintf(bf + ret, size - ret, "%s", 205 ret += repsep_snprintf(bf + ret, size - ret, "%s",
206 self->ms.sym->name); 206 self->ms.sym->name);
207 else 207 else
208 ret += repsep_snprintf(bf + ret, size - ret, "%*Lx", 208 ret += repsep_snprintf(bf + ret, size - ret, "%-#*llx",
209 BITS_PER_LONG / 4, self->ip); 209 BITS_PER_LONG / 4, self->ip);
210 210
211 return ret; 211 return ret;