diff options
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r-- | tools/perf/util/session.c | 107 |
1 files changed, 86 insertions, 21 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 93d355d27109..c3e399bcf18d 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -288,7 +288,8 @@ struct branch_info *machine__resolve_bstack(struct machine *self, | |||
288 | return bi; | 288 | return bi; |
289 | } | 289 | } |
290 | 290 | ||
291 | int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, | 291 | int machine__resolve_callchain(struct machine *self, |
292 | struct perf_evsel *evsel __used, | ||
292 | struct thread *thread, | 293 | struct thread *thread, |
293 | struct ip_callchain *chain, | 294 | struct ip_callchain *chain, |
294 | struct symbol **parent) | 295 | struct symbol **parent) |
@@ -297,7 +298,12 @@ int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, | |||
297 | unsigned int i; | 298 | unsigned int i; |
298 | int err; | 299 | int err; |
299 | 300 | ||
300 | callchain_cursor_reset(&evsel->hists.callchain_cursor); | 301 | callchain_cursor_reset(&callchain_cursor); |
302 | |||
303 | if (chain->nr > PERF_MAX_STACK_DEPTH) { | ||
304 | pr_warning("corrupted callchain. skipping...\n"); | ||
305 | return 0; | ||
306 | } | ||
301 | 307 | ||
302 | for (i = 0; i < chain->nr; i++) { | 308 | for (i = 0; i < chain->nr; i++) { |
303 | u64 ip; | 309 | u64 ip; |
@@ -317,7 +323,14 @@ int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, | |||
317 | case PERF_CONTEXT_USER: | 323 | case PERF_CONTEXT_USER: |
318 | cpumode = PERF_RECORD_MISC_USER; break; | 324 | cpumode = PERF_RECORD_MISC_USER; break; |
319 | default: | 325 | default: |
320 | break; | 326 | pr_debug("invalid callchain context: " |
327 | "%"PRId64"\n", (s64) ip); | ||
328 | /* | ||
329 | * It seems the callchain is corrupted. | ||
330 | * Discard all. | ||
331 | */ | ||
332 | callchain_cursor_reset(&callchain_cursor); | ||
333 | return 0; | ||
321 | } | 334 | } |
322 | continue; | 335 | continue; |
323 | } | 336 | } |
@@ -333,7 +346,7 @@ int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, | |||
333 | break; | 346 | break; |
334 | } | 347 | } |
335 | 348 | ||
336 | err = callchain_cursor_append(&evsel->hists.callchain_cursor, | 349 | err = callchain_cursor_append(&callchain_cursor, |
337 | ip, al.map, al.sym); | 350 | ip, al.map, al.sym); |
338 | if (err) | 351 | if (err) |
339 | return err; | 352 | return err; |
@@ -429,6 +442,16 @@ static void perf_tool__fill_defaults(struct perf_tool *tool) | |||
429 | tool->finished_round = process_finished_round_stub; | 442 | tool->finished_round = process_finished_round_stub; |
430 | } | 443 | } |
431 | } | 444 | } |
445 | |||
446 | void mem_bswap_32(void *src, int byte_size) | ||
447 | { | ||
448 | u32 *m = src; | ||
449 | while (byte_size > 0) { | ||
450 | *m = bswap_32(*m); | ||
451 | byte_size -= sizeof(u32); | ||
452 | ++m; | ||
453 | } | ||
454 | } | ||
432 | 455 | ||
433 | void mem_bswap_64(void *src, int byte_size) | 456 | void mem_bswap_64(void *src, int byte_size) |
434 | { | 457 | { |
@@ -441,37 +464,65 @@ void mem_bswap_64(void *src, int byte_size) | |||
441 | } | 464 | } |
442 | } | 465 | } |
443 | 466 | ||
444 | static void perf_event__all64_swap(union perf_event *event) | 467 | static void swap_sample_id_all(union perf_event *event, void *data) |
468 | { | ||
469 | void *end = (void *) event + event->header.size; | ||
470 | int size = end - data; | ||
471 | |||
472 | BUG_ON(size % sizeof(u64)); | ||
473 | mem_bswap_64(data, size); | ||
474 | } | ||
475 | |||
476 | static void perf_event__all64_swap(union perf_event *event, | ||
477 | bool sample_id_all __used) | ||
445 | { | 478 | { |
446 | struct perf_event_header *hdr = &event->header; | 479 | struct perf_event_header *hdr = &event->header; |
447 | mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); | 480 | mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); |
448 | } | 481 | } |
449 | 482 | ||
450 | static void perf_event__comm_swap(union perf_event *event) | 483 | static void perf_event__comm_swap(union perf_event *event, bool sample_id_all) |
451 | { | 484 | { |
452 | event->comm.pid = bswap_32(event->comm.pid); | 485 | event->comm.pid = bswap_32(event->comm.pid); |
453 | event->comm.tid = bswap_32(event->comm.tid); | 486 | event->comm.tid = bswap_32(event->comm.tid); |
487 | |||
488 | if (sample_id_all) { | ||
489 | void *data = &event->comm.comm; | ||
490 | |||
491 | data += ALIGN(strlen(data) + 1, sizeof(u64)); | ||
492 | swap_sample_id_all(event, data); | ||
493 | } | ||
454 | } | 494 | } |
455 | 495 | ||
456 | static void perf_event__mmap_swap(union perf_event *event) | 496 | static void perf_event__mmap_swap(union perf_event *event, |
497 | bool sample_id_all) | ||
457 | { | 498 | { |
458 | event->mmap.pid = bswap_32(event->mmap.pid); | 499 | event->mmap.pid = bswap_32(event->mmap.pid); |
459 | event->mmap.tid = bswap_32(event->mmap.tid); | 500 | event->mmap.tid = bswap_32(event->mmap.tid); |
460 | event->mmap.start = bswap_64(event->mmap.start); | 501 | event->mmap.start = bswap_64(event->mmap.start); |
461 | event->mmap.len = bswap_64(event->mmap.len); | 502 | event->mmap.len = bswap_64(event->mmap.len); |
462 | event->mmap.pgoff = bswap_64(event->mmap.pgoff); | 503 | event->mmap.pgoff = bswap_64(event->mmap.pgoff); |
504 | |||
505 | if (sample_id_all) { | ||
506 | void *data = &event->mmap.filename; | ||
507 | |||
508 | data += ALIGN(strlen(data) + 1, sizeof(u64)); | ||
509 | swap_sample_id_all(event, data); | ||
510 | } | ||
463 | } | 511 | } |
464 | 512 | ||
465 | static void perf_event__task_swap(union perf_event *event) | 513 | static void perf_event__task_swap(union perf_event *event, bool sample_id_all) |
466 | { | 514 | { |
467 | event->fork.pid = bswap_32(event->fork.pid); | 515 | event->fork.pid = bswap_32(event->fork.pid); |
468 | event->fork.tid = bswap_32(event->fork.tid); | 516 | event->fork.tid = bswap_32(event->fork.tid); |
469 | event->fork.ppid = bswap_32(event->fork.ppid); | 517 | event->fork.ppid = bswap_32(event->fork.ppid); |
470 | event->fork.ptid = bswap_32(event->fork.ptid); | 518 | event->fork.ptid = bswap_32(event->fork.ptid); |
471 | event->fork.time = bswap_64(event->fork.time); | 519 | event->fork.time = bswap_64(event->fork.time); |
520 | |||
521 | if (sample_id_all) | ||
522 | swap_sample_id_all(event, &event->fork + 1); | ||
472 | } | 523 | } |
473 | 524 | ||
474 | static void perf_event__read_swap(union perf_event *event) | 525 | static void perf_event__read_swap(union perf_event *event, bool sample_id_all) |
475 | { | 526 | { |
476 | event->read.pid = bswap_32(event->read.pid); | 527 | event->read.pid = bswap_32(event->read.pid); |
477 | event->read.tid = bswap_32(event->read.tid); | 528 | event->read.tid = bswap_32(event->read.tid); |
@@ -479,6 +530,9 @@ static void perf_event__read_swap(union perf_event *event) | |||
479 | event->read.time_enabled = bswap_64(event->read.time_enabled); | 530 | event->read.time_enabled = bswap_64(event->read.time_enabled); |
480 | event->read.time_running = bswap_64(event->read.time_running); | 531 | event->read.time_running = bswap_64(event->read.time_running); |
481 | event->read.id = bswap_64(event->read.id); | 532 | event->read.id = bswap_64(event->read.id); |
533 | |||
534 | if (sample_id_all) | ||
535 | swap_sample_id_all(event, &event->read + 1); | ||
482 | } | 536 | } |
483 | 537 | ||
484 | static u8 revbyte(u8 b) | 538 | static u8 revbyte(u8 b) |
@@ -530,7 +584,8 @@ void perf_event__attr_swap(struct perf_event_attr *attr) | |||
530 | swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); | 584 | swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); |
531 | } | 585 | } |
532 | 586 | ||
533 | static void perf_event__hdr_attr_swap(union perf_event *event) | 587 | static void perf_event__hdr_attr_swap(union perf_event *event, |
588 | bool sample_id_all __used) | ||
534 | { | 589 | { |
535 | size_t size; | 590 | size_t size; |
536 | 591 | ||
@@ -541,18 +596,21 @@ static void perf_event__hdr_attr_swap(union perf_event *event) | |||
541 | mem_bswap_64(event->attr.id, size); | 596 | mem_bswap_64(event->attr.id, size); |
542 | } | 597 | } |
543 | 598 | ||
544 | static void perf_event__event_type_swap(union perf_event *event) | 599 | static void perf_event__event_type_swap(union perf_event *event, |
600 | bool sample_id_all __used) | ||
545 | { | 601 | { |
546 | event->event_type.event_type.event_id = | 602 | event->event_type.event_type.event_id = |
547 | bswap_64(event->event_type.event_type.event_id); | 603 | bswap_64(event->event_type.event_type.event_id); |
548 | } | 604 | } |
549 | 605 | ||
550 | static void perf_event__tracing_data_swap(union perf_event *event) | 606 | static void perf_event__tracing_data_swap(union perf_event *event, |
607 | bool sample_id_all __used) | ||
551 | { | 608 | { |
552 | event->tracing_data.size = bswap_32(event->tracing_data.size); | 609 | event->tracing_data.size = bswap_32(event->tracing_data.size); |
553 | } | 610 | } |
554 | 611 | ||
555 | typedef void (*perf_event__swap_op)(union perf_event *event); | 612 | typedef void (*perf_event__swap_op)(union perf_event *event, |
613 | bool sample_id_all); | ||
556 | 614 | ||
557 | static perf_event__swap_op perf_event__swap_ops[] = { | 615 | static perf_event__swap_op perf_event__swap_ops[] = { |
558 | [PERF_RECORD_MMAP] = perf_event__mmap_swap, | 616 | [PERF_RECORD_MMAP] = perf_event__mmap_swap, |
@@ -986,6 +1044,15 @@ static int perf_session__process_user_event(struct perf_session *session, union | |||
986 | } | 1044 | } |
987 | } | 1045 | } |
988 | 1046 | ||
1047 | static void event_swap(union perf_event *event, bool sample_id_all) | ||
1048 | { | ||
1049 | perf_event__swap_op swap; | ||
1050 | |||
1051 | swap = perf_event__swap_ops[event->header.type]; | ||
1052 | if (swap) | ||
1053 | swap(event, sample_id_all); | ||
1054 | } | ||
1055 | |||
989 | static int perf_session__process_event(struct perf_session *session, | 1056 | static int perf_session__process_event(struct perf_session *session, |
990 | union perf_event *event, | 1057 | union perf_event *event, |
991 | struct perf_tool *tool, | 1058 | struct perf_tool *tool, |
@@ -994,9 +1061,8 @@ static int perf_session__process_event(struct perf_session *session, | |||
994 | struct perf_sample sample; | 1061 | struct perf_sample sample; |
995 | int ret; | 1062 | int ret; |
996 | 1063 | ||
997 | if (session->header.needs_swap && | 1064 | if (session->header.needs_swap) |
998 | perf_event__swap_ops[event->header.type]) | 1065 | event_swap(event, session->sample_id_all); |
999 | perf_event__swap_ops[event->header.type](event); | ||
1000 | 1066 | ||
1001 | if (event->header.type >= PERF_RECORD_HEADER_MAX) | 1067 | if (event->header.type >= PERF_RECORD_HEADER_MAX) |
1002 | return -EINVAL; | 1068 | return -EINVAL; |
@@ -1428,7 +1494,6 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, | |||
1428 | int print_sym, int print_dso, int print_symoffset) | 1494 | int print_sym, int print_dso, int print_symoffset) |
1429 | { | 1495 | { |
1430 | struct addr_location al; | 1496 | struct addr_location al; |
1431 | struct callchain_cursor *cursor = &evsel->hists.callchain_cursor; | ||
1432 | struct callchain_cursor_node *node; | 1497 | struct callchain_cursor_node *node; |
1433 | 1498 | ||
1434 | if (perf_event__preprocess_sample(event, machine, &al, sample, | 1499 | if (perf_event__preprocess_sample(event, machine, &al, sample, |
@@ -1446,10 +1511,10 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, | |||
1446 | error("Failed to resolve callchain. Skipping\n"); | 1511 | error("Failed to resolve callchain. Skipping\n"); |
1447 | return; | 1512 | return; |
1448 | } | 1513 | } |
1449 | callchain_cursor_commit(cursor); | 1514 | callchain_cursor_commit(&callchain_cursor); |
1450 | 1515 | ||
1451 | while (1) { | 1516 | while (1) { |
1452 | node = callchain_cursor_current(cursor); | 1517 | node = callchain_cursor_current(&callchain_cursor); |
1453 | if (!node) | 1518 | if (!node) |
1454 | break; | 1519 | break; |
1455 | 1520 | ||
@@ -1460,12 +1525,12 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, | |||
1460 | } | 1525 | } |
1461 | if (print_dso) { | 1526 | if (print_dso) { |
1462 | printf(" ("); | 1527 | printf(" ("); |
1463 | map__fprintf_dsoname(al.map, stdout); | 1528 | map__fprintf_dsoname(node->map, stdout); |
1464 | printf(")"); | 1529 | printf(")"); |
1465 | } | 1530 | } |
1466 | printf("\n"); | 1531 | printf("\n"); |
1467 | 1532 | ||
1468 | callchain_cursor_advance(cursor); | 1533 | callchain_cursor_advance(&callchain_cursor); |
1469 | } | 1534 | } |
1470 | 1535 | ||
1471 | } else { | 1536 | } else { |