aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/trace-event-read.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/trace-event-read.c')
-rw-r--r--tools/perf/util/trace-event-read.c473
1 files changed, 177 insertions, 296 deletions
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 3741572696af..af215c0d2379 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -18,8 +18,6 @@
18 * 18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */ 20 */
21#define _FILE_OFFSET_BITS 64
22
23#include <dirent.h> 21#include <dirent.h>
24#include <stdio.h> 22#include <stdio.h>
25#include <stdlib.h> 23#include <stdlib.h>
@@ -41,26 +39,14 @@
41 39
42static int input_fd; 40static int input_fd;
43 41
44static int read_page;
45
46int file_bigendian; 42int file_bigendian;
47int host_bigendian; 43int host_bigendian;
48static int long_size; 44static int long_size;
49 45
50static ssize_t calc_data_size; 46static ssize_t trace_data_size;
51static bool repipe; 47static bool repipe;
52 48
53static void *malloc_or_die(int size) 49static int __do_read(int fd, void *buf, int size)
54{
55 void *ret;
56
57 ret = malloc(size);
58 if (!ret)
59 die("malloc");
60 return ret;
61}
62
63static int do_read(int fd, void *buf, int size)
64{ 50{
65 int rsize = size; 51 int rsize = size;
66 52
@@ -73,8 +59,10 @@ static int do_read(int fd, void *buf, int size)
73 if (repipe) { 59 if (repipe) {
74 int retw = write(STDOUT_FILENO, buf, ret); 60 int retw = write(STDOUT_FILENO, buf, ret);
75 61
76 if (retw <= 0 || retw != ret) 62 if (retw <= 0 || retw != ret) {
77 die("repiping input file"); 63 pr_debug("repiping input file");
64 return -1;
65 }
78 } 66 }
79 67
80 size -= ret; 68 size -= ret;
@@ -84,17 +72,18 @@ static int do_read(int fd, void *buf, int size)
84 return rsize; 72 return rsize;
85} 73}
86 74
87static int read_or_die(void *data, int size) 75static int do_read(void *data, int size)
88{ 76{
89 int r; 77 int r;
90 78
91 r = do_read(input_fd, data, size); 79 r = __do_read(input_fd, data, size);
92 if (r <= 0) 80 if (r <= 0) {
93 die("reading input file (size expected=%d received=%d)", 81 pr_debug("reading input file (size expected=%d received=%d)",
94 size, r); 82 size, r);
83 return -1;
84 }
95 85
96 if (calc_data_size) 86 trace_data_size += r;
97 calc_data_size += r;
98 87
99 return r; 88 return r;
100} 89}
@@ -107,7 +96,7 @@ static void skip(int size)
107 96
108 while (size) { 97 while (size) {
109 r = size > BUFSIZ ? BUFSIZ : size; 98 r = size > BUFSIZ ? BUFSIZ : size;
110 read_or_die(buf, r); 99 do_read(buf, r);
111 size -= r; 100 size -= r;
112 }; 101 };
113} 102}
@@ -116,7 +105,8 @@ static unsigned int read4(struct pevent *pevent)
116{ 105{
117 unsigned int data; 106 unsigned int data;
118 107
119 read_or_die(&data, 4); 108 if (do_read(&data, 4) < 0)
109 return 0;
120 return __data2host4(pevent, data); 110 return __data2host4(pevent, data);
121} 111}
122 112
@@ -124,7 +114,8 @@ static unsigned long long read8(struct pevent *pevent)
124{ 114{
125 unsigned long long data; 115 unsigned long long data;
126 116
127 read_or_die(&data, 8); 117 if (do_read(&data, 8) < 0)
118 return 0;
128 return __data2host8(pevent, data); 119 return __data2host8(pevent, data);
129} 120}
130 121
@@ -138,17 +129,23 @@ static char *read_string(void)
138 129
139 for (;;) { 130 for (;;) {
140 r = read(input_fd, &c, 1); 131 r = read(input_fd, &c, 1);
141 if (r < 0) 132 if (r < 0) {
142 die("reading input file"); 133 pr_debug("reading input file");
134 goto out;
135 }
143 136
144 if (!r) 137 if (!r) {
145 die("no data"); 138 pr_debug("no data");
139 goto out;
140 }
146 141
147 if (repipe) { 142 if (repipe) {
148 int retw = write(STDOUT_FILENO, &c, 1); 143 int retw = write(STDOUT_FILENO, &c, 1);
149 144
150 if (retw <= 0 || retw != r) 145 if (retw <= 0 || retw != r) {
151 die("repiping input file string"); 146 pr_debug("repiping input file string");
147 goto out;
148 }
152 } 149 }
153 150
154 buf[size++] = c; 151 buf[size++] = c;
@@ -157,60 +154,79 @@ static char *read_string(void)
157 break; 154 break;
158 } 155 }
159 156
160 if (calc_data_size) 157 trace_data_size += size;
161 calc_data_size += size;
162
163 str = malloc_or_die(size);
164 memcpy(str, buf, size);
165 158
159 str = malloc(size);
160 if (str)
161 memcpy(str, buf, size);
162out:
166 return str; 163 return str;
167} 164}
168 165
169static void read_proc_kallsyms(struct pevent *pevent) 166static int read_proc_kallsyms(struct pevent *pevent)
170{ 167{
171 unsigned int size; 168 unsigned int size;
172 char *buf; 169 char *buf;
173 170
174 size = read4(pevent); 171 size = read4(pevent);
175 if (!size) 172 if (!size)
176 return; 173 return 0;
174
175 buf = malloc(size + 1);
176 if (buf == NULL)
177 return -1;
177 178
178 buf = malloc_or_die(size + 1); 179 if (do_read(buf, size) < 0) {
179 read_or_die(buf, size); 180 free(buf);
181 return -1;
182 }
180 buf[size] = '\0'; 183 buf[size] = '\0';
181 184
182 parse_proc_kallsyms(pevent, buf, size); 185 parse_proc_kallsyms(pevent, buf, size);
183 186
184 free(buf); 187 free(buf);
188 return 0;
185} 189}
186 190
187static void read_ftrace_printk(struct pevent *pevent) 191static int read_ftrace_printk(struct pevent *pevent)
188{ 192{
189 unsigned int size; 193 unsigned int size;
190 char *buf; 194 char *buf;
191 195
196 /* it can have 0 size */
192 size = read4(pevent); 197 size = read4(pevent);
193 if (!size) 198 if (!size)
194 return; 199 return 0;
200
201 buf = malloc(size);
202 if (buf == NULL)
203 return -1;
195 204
196 buf = malloc_or_die(size); 205 if (do_read(buf, size) < 0) {
197 read_or_die(buf, size); 206 free(buf);
207 return -1;
208 }
198 209
199 parse_ftrace_printk(pevent, buf, size); 210 parse_ftrace_printk(pevent, buf, size);
200 211
201 free(buf); 212 free(buf);
213 return 0;
202} 214}
203 215
204static void read_header_files(struct pevent *pevent) 216static int read_header_files(struct pevent *pevent)
205{ 217{
206 unsigned long long size; 218 unsigned long long size;
207 char *header_event; 219 char *header_event;
208 char buf[BUFSIZ]; 220 char buf[BUFSIZ];
221 int ret = 0;
209 222
210 read_or_die(buf, 12); 223 if (do_read(buf, 12) < 0)
224 return -1;
211 225
212 if (memcmp(buf, "header_page", 12) != 0) 226 if (memcmp(buf, "header_page", 12) != 0) {
213 die("did not read header page"); 227 pr_debug("did not read header page");
228 return -1;
229 }
214 230
215 size = read8(pevent); 231 size = read8(pevent);
216 skip(size); 232 skip(size);
@@ -221,269 +237,107 @@ static void read_header_files(struct pevent *pevent)
221 */ 237 */
222 long_size = header_page_size_size; 238 long_size = header_page_size_size;
223 239
224 read_or_die(buf, 13); 240 if (do_read(buf, 13) < 0)
225 if (memcmp(buf, "header_event", 13) != 0) 241 return -1;
226 die("did not read header event"); 242
243 if (memcmp(buf, "header_event", 13) != 0) {
244 pr_debug("did not read header event");
245 return -1;
246 }
227 247
228 size = read8(pevent); 248 size = read8(pevent);
229 header_event = malloc_or_die(size); 249 header_event = malloc(size);
230 read_or_die(header_event, size); 250 if (header_event == NULL)
251 return -1;
252
253 if (do_read(header_event, size) < 0)
254 ret = -1;
255
231 free(header_event); 256 free(header_event);
257 return ret;
232} 258}
233 259
234static void read_ftrace_file(struct pevent *pevent, unsigned long long size) 260static int read_ftrace_file(struct pevent *pevent, unsigned long long size)
235{ 261{
236 char *buf; 262 char *buf;
237 263
238 buf = malloc_or_die(size); 264 buf = malloc(size);
239 read_or_die(buf, size); 265 if (buf == NULL)
266 return -1;
267
268 if (do_read(buf, size) < 0) {
269 free(buf);
270 return -1;
271 }
272
240 parse_ftrace_file(pevent, buf, size); 273 parse_ftrace_file(pevent, buf, size);
241 free(buf); 274 free(buf);
275 return 0;
242} 276}
243 277
244static void read_event_file(struct pevent *pevent, char *sys, 278static int read_event_file(struct pevent *pevent, char *sys,
245 unsigned long long size) 279 unsigned long long size)
246{ 280{
247 char *buf; 281 char *buf;
248 282
249 buf = malloc_or_die(size); 283 buf = malloc(size);
250 read_or_die(buf, size); 284 if (buf == NULL)
285 return -1;
286
287 if (do_read(buf, size) < 0) {
288 free(buf);
289 return -1;
290 }
291
251 parse_event_file(pevent, buf, size, sys); 292 parse_event_file(pevent, buf, size, sys);
252 free(buf); 293 free(buf);
294 return 0;
253} 295}
254 296
255static void read_ftrace_files(struct pevent *pevent) 297static int read_ftrace_files(struct pevent *pevent)
256{ 298{
257 unsigned long long size; 299 unsigned long long size;
258 int count; 300 int count;
259 int i; 301 int i;
302 int ret;
260 303
261 count = read4(pevent); 304 count = read4(pevent);
262 305
263 for (i = 0; i < count; i++) { 306 for (i = 0; i < count; i++) {
264 size = read8(pevent); 307 size = read8(pevent);
265 read_ftrace_file(pevent, size); 308 ret = read_ftrace_file(pevent, size);
309 if (ret)
310 return ret;
266 } 311 }
312 return 0;
267} 313}
268 314
269static void read_event_files(struct pevent *pevent) 315static int read_event_files(struct pevent *pevent)
270{ 316{
271 unsigned long long size; 317 unsigned long long size;
272 char *sys; 318 char *sys;
273 int systems; 319 int systems;
274 int count; 320 int count;
275 int i,x; 321 int i,x;
322 int ret;
276 323
277 systems = read4(pevent); 324 systems = read4(pevent);
278 325
279 for (i = 0; i < systems; i++) { 326 for (i = 0; i < systems; i++) {
280 sys = read_string(); 327 sys = read_string();
328 if (sys == NULL)
329 return -1;
281 330
282 count = read4(pevent); 331 count = read4(pevent);
332
283 for (x=0; x < count; x++) { 333 for (x=0; x < count; x++) {
284 size = read8(pevent); 334 size = read8(pevent);
285 read_event_file(pevent, sys, size); 335 ret = read_event_file(pevent, sys, size);
336 if (ret)
337 return ret;
286 } 338 }
287 } 339 }
288} 340 return 0;
289
290struct cpu_data {
291 unsigned long long offset;
292 unsigned long long size;
293 unsigned long long timestamp;
294 struct pevent_record *next;
295 char *page;
296 int cpu;
297 int index;
298 int page_size;
299};
300
301static struct cpu_data *cpu_data;
302
303static void update_cpu_data_index(int cpu)
304{
305 cpu_data[cpu].offset += page_size;
306 cpu_data[cpu].size -= page_size;
307 cpu_data[cpu].index = 0;
308}
309
310static void get_next_page(int cpu)
311{
312 off_t save_seek;
313 off_t ret;
314
315 if (!cpu_data[cpu].page)
316 return;
317
318 if (read_page) {
319 if (cpu_data[cpu].size <= page_size) {
320 free(cpu_data[cpu].page);
321 cpu_data[cpu].page = NULL;
322 return;
323 }
324
325 update_cpu_data_index(cpu);
326
327 /* other parts of the code may expect the pointer to not move */
328 save_seek = lseek(input_fd, 0, SEEK_CUR);
329
330 ret = lseek(input_fd, cpu_data[cpu].offset, SEEK_SET);
331 if (ret == (off_t)-1)
332 die("failed to lseek");
333 ret = read(input_fd, cpu_data[cpu].page, page_size);
334 if (ret < 0)
335 die("failed to read page");
336
337 /* reset the file pointer back */
338 lseek(input_fd, save_seek, SEEK_SET);
339
340 return;
341 }
342
343 munmap(cpu_data[cpu].page, page_size);
344 cpu_data[cpu].page = NULL;
345
346 if (cpu_data[cpu].size <= page_size)
347 return;
348
349 update_cpu_data_index(cpu);
350
351 cpu_data[cpu].page = mmap(NULL, page_size, PROT_READ, MAP_PRIVATE,
352 input_fd, cpu_data[cpu].offset);
353 if (cpu_data[cpu].page == MAP_FAILED)
354 die("failed to mmap cpu %d at offset 0x%llx",
355 cpu, cpu_data[cpu].offset);
356}
357
358static unsigned int type_len4host(unsigned int type_len_ts)
359{
360 if (file_bigendian)
361 return (type_len_ts >> 27) & ((1 << 5) - 1);
362 else
363 return type_len_ts & ((1 << 5) - 1);
364}
365
366static unsigned int ts4host(unsigned int type_len_ts)
367{
368 if (file_bigendian)
369 return type_len_ts & ((1 << 27) - 1);
370 else
371 return type_len_ts >> 5;
372}
373
374static int calc_index(void *ptr, int cpu)
375{
376 return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page;
377}
378
379struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu)
380{
381 struct pevent_record *data;
382 void *page = cpu_data[cpu].page;
383 int idx = cpu_data[cpu].index;
384 void *ptr = page + idx;
385 unsigned long long extend;
386 unsigned int type_len_ts;
387 unsigned int type_len;
388 unsigned int delta;
389 unsigned int length = 0;
390
391 if (cpu_data[cpu].next)
392 return cpu_data[cpu].next;
393
394 if (!page)
395 return NULL;
396
397 if (!idx) {
398 /* FIXME: handle header page */
399 if (header_page_ts_size != 8)
400 die("expected a long long type for timestamp");
401 cpu_data[cpu].timestamp = data2host8(pevent, ptr);
402 ptr += 8;
403 switch (header_page_size_size) {
404 case 4:
405 cpu_data[cpu].page_size = data2host4(pevent, ptr);
406 ptr += 4;
407 break;
408 case 8:
409 cpu_data[cpu].page_size = data2host8(pevent, ptr);
410 ptr += 8;
411 break;
412 default:
413 die("bad long size");
414 }
415 ptr = cpu_data[cpu].page + header_page_data_offset;
416 }
417
418read_again:
419 idx = calc_index(ptr, cpu);
420
421 if (idx >= cpu_data[cpu].page_size) {
422 get_next_page(cpu);
423 return trace_peek_data(pevent, cpu);
424 }
425
426 type_len_ts = data2host4(pevent, ptr);
427 ptr += 4;
428
429 type_len = type_len4host(type_len_ts);
430 delta = ts4host(type_len_ts);
431
432 switch (type_len) {
433 case RINGBUF_TYPE_PADDING:
434 if (!delta)
435 die("error, hit unexpected end of page");
436 length = data2host4(pevent, ptr);
437 ptr += 4;
438 length *= 4;
439 ptr += length;
440 goto read_again;
441
442 case RINGBUF_TYPE_TIME_EXTEND:
443 extend = data2host4(pevent, ptr);
444 ptr += 4;
445 extend <<= TS_SHIFT;
446 extend += delta;
447 cpu_data[cpu].timestamp += extend;
448 goto read_again;
449
450 case RINGBUF_TYPE_TIME_STAMP:
451 ptr += 12;
452 break;
453 case 0:
454 length = data2host4(pevent, ptr);
455 ptr += 4;
456 die("here! length=%d", length);
457 break;
458 default:
459 length = type_len * 4;
460 break;
461 }
462
463 cpu_data[cpu].timestamp += delta;
464
465 data = malloc_or_die(sizeof(*data));
466 memset(data, 0, sizeof(*data));
467
468 data->ts = cpu_data[cpu].timestamp;
469 data->size = length;
470 data->data = ptr;
471 ptr += length;
472
473 cpu_data[cpu].index = calc_index(ptr, cpu);
474 cpu_data[cpu].next = data;
475
476 return data;
477}
478
479struct pevent_record *trace_read_data(struct pevent *pevent, int cpu)
480{
481 struct pevent_record *data;
482
483 data = trace_peek_data(pevent, cpu);
484 cpu_data[cpu].next = NULL;
485
486 return data;
487} 341}
488 342
489ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) 343ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
@@ -494,58 +348,85 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
494 int show_version = 0; 348 int show_version = 0;
495 int show_funcs = 0; 349 int show_funcs = 0;
496 int show_printk = 0; 350 int show_printk = 0;
497 ssize_t size; 351 ssize_t size = -1;
352 struct pevent *pevent;
353 int err;
498 354
499 calc_data_size = 1; 355 *ppevent = NULL;
500 repipe = __repipe;
501 356
357 repipe = __repipe;
502 input_fd = fd; 358 input_fd = fd;
503 359
504 read_or_die(buf, 3); 360 if (do_read(buf, 3) < 0)
505 if (memcmp(buf, test, 3) != 0) 361 return -1;
506 die("no trace data in the file"); 362 if (memcmp(buf, test, 3) != 0) {
363 pr_debug("no trace data in the file");
364 return -1;
365 }
507 366
508 read_or_die(buf, 7); 367 if (do_read(buf, 7) < 0)
509 if (memcmp(buf, "tracing", 7) != 0) 368 return -1;
510 die("not a trace file (missing 'tracing' tag)"); 369 if (memcmp(buf, "tracing", 7) != 0) {
370 pr_debug("not a trace file (missing 'tracing' tag)");
371 return -1;
372 }
511 373
512 version = read_string(); 374 version = read_string();
375 if (version == NULL)
376 return -1;
513 if (show_version) 377 if (show_version)
514 printf("version = %s\n", version); 378 printf("version = %s\n", version);
515 free(version); 379 free(version);
516 380
517 read_or_die(buf, 1); 381 if (do_read(buf, 1) < 0)
382 return -1;
518 file_bigendian = buf[0]; 383 file_bigendian = buf[0];
519 host_bigendian = bigendian(); 384 host_bigendian = bigendian();
520 385
521 *ppevent = read_trace_init(file_bigendian, host_bigendian); 386 pevent = read_trace_init(file_bigendian, host_bigendian);
522 if (*ppevent == NULL) 387 if (pevent == NULL) {
523 die("read_trace_init failed"); 388 pr_debug("read_trace_init failed");
389 goto out;
390 }
524 391
525 read_or_die(buf, 1); 392 if (do_read(buf, 1) < 0)
393 goto out;
526 long_size = buf[0]; 394 long_size = buf[0];
527 395
528 page_size = read4(*ppevent); 396 page_size = read4(pevent);
529 397 if (!page_size)
530 read_header_files(*ppevent); 398 goto out;
531 399
532 read_ftrace_files(*ppevent); 400 err = read_header_files(pevent);
533 read_event_files(*ppevent); 401 if (err)
534 read_proc_kallsyms(*ppevent); 402 goto out;
535 read_ftrace_printk(*ppevent); 403 err = read_ftrace_files(pevent);
536 404 if (err)
537 size = calc_data_size - 1; 405 goto out;
538 calc_data_size = 0; 406 err = read_event_files(pevent);
407 if (err)
408 goto out;
409 err = read_proc_kallsyms(pevent);
410 if (err)
411 goto out;
412 err = read_ftrace_printk(pevent);
413 if (err)
414 goto out;
415
416 size = trace_data_size;
539 repipe = false; 417 repipe = false;
540 418
541 if (show_funcs) { 419 if (show_funcs) {
542 pevent_print_funcs(*ppevent); 420 pevent_print_funcs(pevent);
543 return size; 421 } else if (show_printk) {
544 } 422 pevent_print_printk(pevent);
545 if (show_printk) {
546 pevent_print_printk(*ppevent);
547 return size;
548 } 423 }
549 424
425 *ppevent = pevent;
426 pevent = NULL;
427
428out:
429 if (pevent)
430 pevent_free(pevent);
550 return size; 431 return size;
551} 432}