diff options
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/event.h | 7 | ||||
-rw-r--r-- | tools/perf/util/header.c | 52 | ||||
-rw-r--r-- | tools/perf/util/header.h | 6 | ||||
-rw-r--r-- | tools/perf/util/session.c | 13 | ||||
-rw-r--r-- | tools/perf/util/session.h | 3 | ||||
-rw-r--r-- | tools/perf/util/trace-event-info.c | 24 | ||||
-rw-r--r-- | tools/perf/util/trace-event-read.c | 89 | ||||
-rw-r--r-- | tools/perf/util/trace-event.h | 4 |
8 files changed, 152 insertions, 46 deletions
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 { | |||
86 | enum perf_header_event_type { /* above any possible kernel type */ | 86 | enum 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 | ||
111 | struct tracing_data_event { | ||
112 | struct perf_event_header header; | ||
113 | u32 size; | ||
114 | }; | ||
115 | |||
110 | typedef union event_union { | 116 | typedef 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 | ||
123 | struct events_stats { | 130 | struct 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 | |||
938 | int 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 | |||
966 | int 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, | |||
111 | int event__process_event_type(event_t *self, | 111 | int event__process_event_type(event_t *self, |
112 | struct perf_session *session); | 112 | struct perf_session *session); |
113 | 113 | ||
114 | int 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); | ||
118 | int 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 | ||
209 | static const char *event__name[] = { | 211 | static 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 | ||
224 | unsigned long event__total[PERF_RECORD_HEADER_MAX]; | 227 | unsigned 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 | ||
317 | static void event__tracing_data_swap(event_t *self) | ||
318 | { | ||
319 | self->tracing_data.size = bswap_32(self->tracing_data.size); | ||
320 | } | ||
321 | |||
314 | typedef void (*event__swap_op)(event_t *self); | 322 | typedef void (*event__swap_op)(event_t *self); |
315 | 323 | ||
316 | static event__swap_op event__swap_ops[] = { | 324 | static 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 | ||
52 | struct perf_session *perf_session__new(const char *filename, int mode, bool force); | 53 | struct 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 | ||
157 | static ssize_t calc_data_size; | ||
158 | |||
157 | static ssize_t write_or_die(const void *buf, size_t len) | 159 | static 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 | |||
537 | ssize_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 | ||
51 | static unsigned long page_size; | 51 | static unsigned long page_size; |
52 | 52 | ||
53 | static ssize_t calc_data_size; | ||
54 | |||
55 | static 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 | |||
53 | static int read_or_die(void *data, int size) | 72 | static 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 | ||
462 | void trace_report(int fd) | 457 | ssize_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 | ||
164 | void parse_set_info(int nr_cpus, int long_sz); | 164 | void parse_set_info(int nr_cpus, int long_sz); |
165 | 165 | ||
166 | void trace_report(int fd); | 166 | ssize_t trace_report(int fd); |
167 | 167 | ||
168 | void *malloc_or_die(unsigned int size); | 168 | void *malloc_or_die(unsigned int size); |
169 | 169 | ||
@@ -259,6 +259,8 @@ void *raw_field_ptr(struct event *event, const char *name, void *data); | |||
259 | unsigned long long eval_flag(const char *flag); | 259 | unsigned long long eval_flag(const char *flag); |
260 | 260 | ||
261 | int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events); | 261 | int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events); |
262 | ssize_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 */ |
264 | enum trace_flag_type { | 266 | enum trace_flag_type { |