aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-record.c16
-rw-r--r--tools/perf/builtin-report.c1
-rw-r--r--tools/perf/builtin-trace.c1
-rw-r--r--tools/perf/util/event.h7
-rw-r--r--tools/perf/util/header.c52
-rw-r--r--tools/perf/util/header.h6
-rw-r--r--tools/perf/util/session.c13
-rw-r--r--tools/perf/util/session.h3
-rw-r--r--tools/perf/util/trace-event-info.c24
-rw-r--r--tools/perf/util/trace-event-read.c89
-rw-r--r--tools/perf/util/trace-event.h4
11 files changed, 170 insertions, 46 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index c4c132205ed6..3775abe2af78 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -104,6 +104,11 @@ static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
104 pc->data_tail = tail; 104 pc->data_tail = tail;
105} 105}
106 106
107static void advance_output(size_t size)
108{
109 bytes_written += size;
110}
111
107static void write_output(void *buf, size_t size) 112static void write_output(void *buf, size_t size)
108{ 113{
109 while (size) { 114 while (size) {
@@ -599,6 +604,17 @@ static int __cmd_record(int argc, const char **argv)
599 pr_err("Couldn't synthesize event_types.\n"); 604 pr_err("Couldn't synthesize event_types.\n");
600 return err; 605 return err;
601 } 606 }
607
608 err = event__synthesize_tracing_data(output, attrs,
609 nr_counters,
610 process_synthesized_event,
611 session);
612 if (err <= 0) {
613 pr_err("Couldn't record tracing data.\n");
614 return err;
615 }
616
617 advance_output(err);
602 } 618 }
603 619
604 err = event__synthesize_kernel_mmap(process_synthesized_event, 620 err = event__synthesize_kernel_mmap(process_synthesized_event,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index e59d0127d5e3..76f03a70aaca 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -269,6 +269,7 @@ static struct perf_event_ops event_ops = {
269 .read = process_read_event, 269 .read = process_read_event,
270 .attr = event__process_attr, 270 .attr = event__process_attr,
271 .event_type = event__process_event_type, 271 .event_type = event__process_event_type,
272 .tracing_data = event__process_tracing_data,
272}; 273};
273 274
274extern volatile int session_done; 275extern volatile int session_done;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index eb884a7dc24b..1509744429c8 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -106,6 +106,7 @@ static struct perf_event_ops event_ops = {
106 .comm = event__process_comm, 106 .comm = event__process_comm,
107 .attr = event__process_attr, 107 .attr = event__process_attr,
108 .event_type = event__process_event_type, 108 .event_type = event__process_event_type,
109 .tracing_data = event__process_tracing_data,
109}; 110};
110 111
111extern volatile int session_done; 112extern volatile int session_done;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c720fe06f8d7..b896a177ea41 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -86,6 +86,7 @@ struct build_id_event {
86enum perf_header_event_type { /* above any possible kernel type */ 86enum perf_header_event_type { /* above any possible kernel type */
87 PERF_RECORD_HEADER_ATTR = 64, 87 PERF_RECORD_HEADER_ATTR = 64,
88 PERF_RECORD_HEADER_EVENT_TYPE = 65, 88 PERF_RECORD_HEADER_EVENT_TYPE = 65,
89 PERF_RECORD_HEADER_TRACING_DATA = 66,
89 PERF_RECORD_HEADER_MAX 90 PERF_RECORD_HEADER_MAX
90}; 91};
91 92
@@ -107,6 +108,11 @@ struct event_type_event {
107 struct perf_trace_event_type event_type; 108 struct perf_trace_event_type event_type;
108}; 109};
109 110
111struct tracing_data_event {
112 struct perf_event_header header;
113 u32 size;
114};
115
110typedef union event_union { 116typedef union event_union {
111 struct perf_event_header header; 117 struct perf_event_header header;
112 struct ip_event ip; 118 struct ip_event ip;
@@ -118,6 +124,7 @@ typedef union event_union {
118 struct sample_event sample; 124 struct sample_event sample;
119 struct attr_event attr; 125 struct attr_event attr;
120 struct event_type_event event_type; 126 struct event_type_event event_type;
127 struct tracing_data_event tracing_data;
121} event_t; 128} event_t;
122 129
123struct events_stats { 130struct events_stats {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 44637999dbc1..c6874ecc90b8 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -934,3 +934,55 @@ int event__process_event_type(event_t *self,
934 934
935 return 0; 935 return 0;
936} 936}
937
938int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
939 int nb_events,
940 event__handler_t process,
941 struct perf_session *session __unused)
942{
943 event_t ev;
944 ssize_t size = 0, aligned_size = 0, padding;
945 int err = 0;
946
947 memset(&ev, 0, sizeof(ev));
948
949 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
950 size = read_tracing_data_size(fd, pattrs, nb_events);
951 if (size <= 0)
952 return size;
953 aligned_size = ALIGN(size, sizeof(u64));
954 padding = aligned_size - size;
955 ev.tracing_data.header.size = sizeof(ev.tracing_data);
956 ev.tracing_data.size = aligned_size;
957
958 process(&ev, session);
959
960 err = read_tracing_data(fd, pattrs, nb_events);
961 write_padded(fd, NULL, 0, padding);
962
963 return aligned_size;
964}
965
966int event__process_tracing_data(event_t *self,
967 struct perf_session *session)
968{
969 ssize_t size_read, padding, size = self->tracing_data.size;
970 off_t offset = lseek(session->fd, 0, SEEK_CUR);
971 char buf[BUFSIZ];
972
973 /* setup for reading amidst mmap */
974 lseek(session->fd, offset + sizeof(struct tracing_data_event),
975 SEEK_SET);
976
977 size_read = trace_report(session->fd);
978
979 padding = ALIGN(size_read, sizeof(u64)) - size_read;
980
981 if (read(session->fd, buf, padding) < 0)
982 die("reading input file");
983
984 if (size_read + padding != size)
985 die("tracing data size mismatch");
986
987 return size_read + padding;
988}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index afeb61883766..3ed3d98c81d4 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -111,5 +111,11 @@ int event__synthesize_event_types(event__handler_t process,
111int event__process_event_type(event_t *self, 111int event__process_event_type(event_t *self,
112 struct perf_session *session); 112 struct perf_session *session);
113 113
114int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
115 int nb_events,
116 event__handler_t process,
117 struct perf_session *session);
118int event__process_tracing_data(event_t *self,
119 struct perf_session *session);
114 120
115#endif /* __PERF_HEADER_H */ 121#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 96c4629b7740..1516c40d47ac 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -204,6 +204,8 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
204 handler->attr = process_event_stub; 204 handler->attr = process_event_stub;
205 if (handler->event_type == NULL) 205 if (handler->event_type == NULL)
206 handler->event_type = process_event_stub; 206 handler->event_type = process_event_stub;
207 if (handler->tracing_data == NULL)
208 handler->tracing_data = process_event_stub;
207} 209}
208 210
209static const char *event__name[] = { 211static const char *event__name[] = {
@@ -219,6 +221,7 @@ static const char *event__name[] = {
219 [PERF_RECORD_SAMPLE] = "SAMPLE", 221 [PERF_RECORD_SAMPLE] = "SAMPLE",
220 [PERF_RECORD_HEADER_ATTR] = "ATTR", 222 [PERF_RECORD_HEADER_ATTR] = "ATTR",
221 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", 223 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
224 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
222}; 225};
223 226
224unsigned long event__total[PERF_RECORD_HEADER_MAX]; 227unsigned long event__total[PERF_RECORD_HEADER_MAX];
@@ -311,6 +314,11 @@ static void event__event_type_swap(event_t *self)
311 bswap_64(self->event_type.event_type.event_id); 314 bswap_64(self->event_type.event_type.event_id);
312} 315}
313 316
317static void event__tracing_data_swap(event_t *self)
318{
319 self->tracing_data.size = bswap_32(self->tracing_data.size);
320}
321
314typedef void (*event__swap_op)(event_t *self); 322typedef void (*event__swap_op)(event_t *self);
315 323
316static event__swap_op event__swap_ops[] = { 324static event__swap_op event__swap_ops[] = {
@@ -323,6 +331,7 @@ static event__swap_op event__swap_ops[] = {
323 [PERF_RECORD_SAMPLE] = event__all64_swap, 331 [PERF_RECORD_SAMPLE] = event__all64_swap,
324 [PERF_RECORD_HEADER_ATTR] = event__attr_swap, 332 [PERF_RECORD_HEADER_ATTR] = event__attr_swap,
325 [PERF_RECORD_HEADER_EVENT_TYPE] = event__event_type_swap, 333 [PERF_RECORD_HEADER_EVENT_TYPE] = event__event_type_swap,
334 [PERF_RECORD_HEADER_TRACING_DATA] = event__tracing_data_swap,
326 [PERF_RECORD_HEADER_MAX] = NULL, 335 [PERF_RECORD_HEADER_MAX] = NULL,
327}; 336};
328 337
@@ -367,6 +376,10 @@ static int perf_session__process_event(struct perf_session *self,
367 return ops->attr(event, self); 376 return ops->attr(event, self);
368 case PERF_RECORD_HEADER_EVENT_TYPE: 377 case PERF_RECORD_HEADER_EVENT_TYPE:
369 return ops->event_type(event, self); 378 return ops->event_type(event, self);
379 case PERF_RECORD_HEADER_TRACING_DATA:
380 /* setup for reading amidst mmap */
381 lseek(self->fd, offset + head, SEEK_SET);
382 return ops->tracing_data(event, self);
370 default: 383 default:
371 self->unknown_events++; 384 self->unknown_events++;
372 return -1; 385 return -1;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 0dac1f4457d3..0739ebbbf9fd 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -46,7 +46,8 @@ struct perf_event_ops {
46 throttle, 46 throttle,
47 unthrottle, 47 unthrottle,
48 attr, 48 attr,
49 event_type; 49 event_type,
50 tracing_data;
50}; 51};
51 52
52struct perf_session *perf_session__new(const char *filename, int mode, bool force); 53struct perf_session *perf_session__new(const char *filename, int mode, bool force);
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index 5ea8973ad331..30cd9b575953 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -154,10 +154,17 @@ static void put_tracing_file(char *file)
154 free(file); 154 free(file);
155} 155}
156 156
157static ssize_t calc_data_size;
158
157static ssize_t write_or_die(const void *buf, size_t len) 159static ssize_t write_or_die(const void *buf, size_t len)
158{ 160{
159 int ret; 161 int ret;
160 162
163 if (calc_data_size) {
164 calc_data_size += len;
165 return len;
166 }
167
161 ret = write(output_fd, buf, len); 168 ret = write(output_fd, buf, len);
162 if (ret < 0) 169 if (ret < 0)
163 die("writing to '%s'", output_file); 170 die("writing to '%s'", output_file);
@@ -526,3 +533,20 @@ int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events)
526 533
527 return 0; 534 return 0;
528} 535}
536
537ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs,
538 int nb_events)
539{
540 ssize_t size;
541 int err = 0;
542
543 calc_data_size = 1;
544 err = read_tracing_data(fd, pattrs, nb_events);
545 size = calc_data_size - 1;
546 calc_data_size = 0;
547
548 if (err < 0)
549 return err;
550
551 return size;
552}
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 7cd1193918c7..44889c9b5630 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -50,14 +50,37 @@ static int long_size;
50 50
51static unsigned long page_size; 51static unsigned long page_size;
52 52
53static ssize_t calc_data_size;
54
55static int do_read(int fd, void *buf, int size)
56{
57 int rsize = size;
58
59 while (size) {
60 int ret = read(fd, buf, size);
61
62 if (ret <= 0)
63 return -1;
64
65 size -= ret;
66 buf += ret;
67 }
68
69 return rsize;
70}
71
53static int read_or_die(void *data, int size) 72static int read_or_die(void *data, int size)
54{ 73{
55 int r; 74 int r;
56 75
57 r = read(input_fd, data, size); 76 r = do_read(input_fd, data, size);
58 if (r != size) 77 if (r <= 0)
59 die("reading input file (size expected=%d received=%d)", 78 die("reading input file (size expected=%d received=%d)",
60 size, r); 79 size, r);
80
81 if (calc_data_size)
82 calc_data_size += r;
83
61 return r; 84 return r;
62} 85}
63 86
@@ -82,56 +105,28 @@ static char *read_string(void)
82 char buf[BUFSIZ]; 105 char buf[BUFSIZ];
83 char *str = NULL; 106 char *str = NULL;
84 int size = 0; 107 int size = 0;
85 int i;
86 off_t r; 108 off_t r;
109 char c;
87 110
88 for (;;) { 111 for (;;) {
89 r = read(input_fd, buf, BUFSIZ); 112 r = read(input_fd, &c, 1);
90 if (r < 0) 113 if (r < 0)
91 die("reading input file"); 114 die("reading input file");
92 115
93 if (!r) 116 if (!r)
94 die("no data"); 117 die("no data");
95 118
96 for (i = 0; i < r; i++) { 119 buf[size++] = c;
97 if (!buf[i])
98 break;
99 }
100 if (i < r)
101 break;
102 120
103 if (str) { 121 if (!c)
104 size += BUFSIZ; 122 break;
105 str = realloc(str, size);
106 if (!str)
107 die("malloc of size %d", size);
108 memcpy(str + (size - BUFSIZ), buf, BUFSIZ);
109 } else {
110 size = BUFSIZ;
111 str = malloc_or_die(size);
112 memcpy(str, buf, size);
113 }
114 } 123 }
115 124
116 /* trailing \0: */ 125 if (calc_data_size)
117 i++; 126 calc_data_size += size;
118 127
119 /* move the file descriptor to the end of the string */ 128 str = malloc_or_die(size);
120 r = lseek(input_fd, -(r - i), SEEK_CUR); 129 memcpy(str, buf, size);
121 if (r == (off_t)-1)
122 die("lseek");
123
124 if (str) {
125 size += i;
126 str = realloc(str, size);
127 if (!str)
128 die("malloc of size %d", size);
129 memcpy(str + (size - i), buf, i);
130 } else {
131 size = i;
132 str = malloc_or_die(i);
133 memcpy(str, buf, i);
134 }
135 130
136 return str; 131 return str;
137} 132}
@@ -459,7 +454,7 @@ struct record *trace_read_data(int cpu)
459 return data; 454 return data;
460} 455}
461 456
462void trace_report(int fd) 457ssize_t trace_report(int fd)
463{ 458{
464 char buf[BUFSIZ]; 459 char buf[BUFSIZ];
465 char test[] = { 23, 8, 68 }; 460 char test[] = { 23, 8, 68 };
@@ -467,6 +462,9 @@ void trace_report(int fd)
467 int show_version = 0; 462 int show_version = 0;
468 int show_funcs = 0; 463 int show_funcs = 0;
469 int show_printk = 0; 464 int show_printk = 0;
465 ssize_t size;
466
467 calc_data_size = 1;
470 468
471 input_fd = fd; 469 input_fd = fd;
472 470
@@ -499,14 +497,17 @@ void trace_report(int fd)
499 read_proc_kallsyms(); 497 read_proc_kallsyms();
500 read_ftrace_printk(); 498 read_ftrace_printk();
501 499
500 size = calc_data_size - 1;
501 calc_data_size = 0;
502
502 if (show_funcs) { 503 if (show_funcs) {
503 print_funcs(); 504 print_funcs();
504 return; 505 return size;
505 } 506 }
506 if (show_printk) { 507 if (show_printk) {
507 print_printk(); 508 print_printk();
508 return; 509 return size;
509 } 510 }
510 511
511 return; 512 return size;
512} 513}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 81f2fd20a0ea..1f45d468fd9a 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -163,7 +163,7 @@ struct record *trace_read_data(int cpu);
163 163
164void parse_set_info(int nr_cpus, int long_sz); 164void parse_set_info(int nr_cpus, int long_sz);
165 165
166void trace_report(int fd); 166ssize_t trace_report(int fd);
167 167
168void *malloc_or_die(unsigned int size); 168void *malloc_or_die(unsigned int size);
169 169
@@ -259,6 +259,8 @@ void *raw_field_ptr(struct event *event, const char *name, void *data);
259unsigned long long eval_flag(const char *flag); 259unsigned long long eval_flag(const char *flag);
260 260
261int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events); 261int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events);
262ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs,
263 int nb_events);
262 264
263/* taken from kernel/trace/trace.h */ 265/* taken from kernel/trace/trace.h */
264enum trace_flag_type { 266enum trace_flag_type {