diff options
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r-- | tools/perf/util/session.c | 97 |
1 files changed, 76 insertions, 21 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 93d355d27109..2600916efa83 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; |
@@ -441,37 +454,65 @@ void mem_bswap_64(void *src, int byte_size) | |||
441 | } | 454 | } |
442 | } | 455 | } |
443 | 456 | ||
444 | static void perf_event__all64_swap(union perf_event *event) | 457 | static void swap_sample_id_all(union perf_event *event, void *data) |
458 | { | ||
459 | void *end = (void *) event + event->header.size; | ||
460 | int size = end - data; | ||
461 | |||
462 | BUG_ON(size % sizeof(u64)); | ||
463 | mem_bswap_64(data, size); | ||
464 | } | ||
465 | |||
466 | static void perf_event__all64_swap(union perf_event *event, | ||
467 | bool sample_id_all __used) | ||
445 | { | 468 | { |
446 | struct perf_event_header *hdr = &event->header; | 469 | struct perf_event_header *hdr = &event->header; |
447 | mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); | 470 | mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); |
448 | } | 471 | } |
449 | 472 | ||
450 | static void perf_event__comm_swap(union perf_event *event) | 473 | static void perf_event__comm_swap(union perf_event *event, bool sample_id_all) |
451 | { | 474 | { |
452 | event->comm.pid = bswap_32(event->comm.pid); | 475 | event->comm.pid = bswap_32(event->comm.pid); |
453 | event->comm.tid = bswap_32(event->comm.tid); | 476 | event->comm.tid = bswap_32(event->comm.tid); |
477 | |||
478 | if (sample_id_all) { | ||
479 | void *data = &event->comm.comm; | ||
480 | |||
481 | data += ALIGN(strlen(data) + 1, sizeof(u64)); | ||
482 | swap_sample_id_all(event, data); | ||
483 | } | ||
454 | } | 484 | } |
455 | 485 | ||
456 | static void perf_event__mmap_swap(union perf_event *event) | 486 | static void perf_event__mmap_swap(union perf_event *event, |
487 | bool sample_id_all) | ||
457 | { | 488 | { |
458 | event->mmap.pid = bswap_32(event->mmap.pid); | 489 | event->mmap.pid = bswap_32(event->mmap.pid); |
459 | event->mmap.tid = bswap_32(event->mmap.tid); | 490 | event->mmap.tid = bswap_32(event->mmap.tid); |
460 | event->mmap.start = bswap_64(event->mmap.start); | 491 | event->mmap.start = bswap_64(event->mmap.start); |
461 | event->mmap.len = bswap_64(event->mmap.len); | 492 | event->mmap.len = bswap_64(event->mmap.len); |
462 | event->mmap.pgoff = bswap_64(event->mmap.pgoff); | 493 | event->mmap.pgoff = bswap_64(event->mmap.pgoff); |
494 | |||
495 | if (sample_id_all) { | ||
496 | void *data = &event->mmap.filename; | ||
497 | |||
498 | data += ALIGN(strlen(data) + 1, sizeof(u64)); | ||
499 | swap_sample_id_all(event, data); | ||
500 | } | ||
463 | } | 501 | } |
464 | 502 | ||
465 | static void perf_event__task_swap(union perf_event *event) | 503 | static void perf_event__task_swap(union perf_event *event, bool sample_id_all) |
466 | { | 504 | { |
467 | event->fork.pid = bswap_32(event->fork.pid); | 505 | event->fork.pid = bswap_32(event->fork.pid); |
468 | event->fork.tid = bswap_32(event->fork.tid); | 506 | event->fork.tid = bswap_32(event->fork.tid); |
469 | event->fork.ppid = bswap_32(event->fork.ppid); | 507 | event->fork.ppid = bswap_32(event->fork.ppid); |
470 | event->fork.ptid = bswap_32(event->fork.ptid); | 508 | event->fork.ptid = bswap_32(event->fork.ptid); |
471 | event->fork.time = bswap_64(event->fork.time); | 509 | event->fork.time = bswap_64(event->fork.time); |
510 | |||
511 | if (sample_id_all) | ||
512 | swap_sample_id_all(event, &event->fork + 1); | ||
472 | } | 513 | } |
473 | 514 | ||
474 | static void perf_event__read_swap(union perf_event *event) | 515 | static void perf_event__read_swap(union perf_event *event, bool sample_id_all) |
475 | { | 516 | { |
476 | event->read.pid = bswap_32(event->read.pid); | 517 | event->read.pid = bswap_32(event->read.pid); |
477 | event->read.tid = bswap_32(event->read.tid); | 518 | event->read.tid = bswap_32(event->read.tid); |
@@ -479,6 +520,9 @@ static void perf_event__read_swap(union perf_event *event) | |||
479 | event->read.time_enabled = bswap_64(event->read.time_enabled); | 520 | event->read.time_enabled = bswap_64(event->read.time_enabled); |
480 | event->read.time_running = bswap_64(event->read.time_running); | 521 | event->read.time_running = bswap_64(event->read.time_running); |
481 | event->read.id = bswap_64(event->read.id); | 522 | event->read.id = bswap_64(event->read.id); |
523 | |||
524 | if (sample_id_all) | ||
525 | swap_sample_id_all(event, &event->read + 1); | ||
482 | } | 526 | } |
483 | 527 | ||
484 | static u8 revbyte(u8 b) | 528 | static u8 revbyte(u8 b) |
@@ -530,7 +574,8 @@ void perf_event__attr_swap(struct perf_event_attr *attr) | |||
530 | swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); | 574 | swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); |
531 | } | 575 | } |
532 | 576 | ||
533 | static void perf_event__hdr_attr_swap(union perf_event *event) | 577 | static void perf_event__hdr_attr_swap(union perf_event *event, |
578 | bool sample_id_all __used) | ||
534 | { | 579 | { |
535 | size_t size; | 580 | size_t size; |
536 | 581 | ||
@@ -541,18 +586,21 @@ static void perf_event__hdr_attr_swap(union perf_event *event) | |||
541 | mem_bswap_64(event->attr.id, size); | 586 | mem_bswap_64(event->attr.id, size); |
542 | } | 587 | } |
543 | 588 | ||
544 | static void perf_event__event_type_swap(union perf_event *event) | 589 | static void perf_event__event_type_swap(union perf_event *event, |
590 | bool sample_id_all __used) | ||
545 | { | 591 | { |
546 | event->event_type.event_type.event_id = | 592 | event->event_type.event_type.event_id = |
547 | bswap_64(event->event_type.event_type.event_id); | 593 | bswap_64(event->event_type.event_type.event_id); |
548 | } | 594 | } |
549 | 595 | ||
550 | static void perf_event__tracing_data_swap(union perf_event *event) | 596 | static void perf_event__tracing_data_swap(union perf_event *event, |
597 | bool sample_id_all __used) | ||
551 | { | 598 | { |
552 | event->tracing_data.size = bswap_32(event->tracing_data.size); | 599 | event->tracing_data.size = bswap_32(event->tracing_data.size); |
553 | } | 600 | } |
554 | 601 | ||
555 | typedef void (*perf_event__swap_op)(union perf_event *event); | 602 | typedef void (*perf_event__swap_op)(union perf_event *event, |
603 | bool sample_id_all); | ||
556 | 604 | ||
557 | static perf_event__swap_op perf_event__swap_ops[] = { | 605 | static perf_event__swap_op perf_event__swap_ops[] = { |
558 | [PERF_RECORD_MMAP] = perf_event__mmap_swap, | 606 | [PERF_RECORD_MMAP] = perf_event__mmap_swap, |
@@ -986,6 +1034,15 @@ static int perf_session__process_user_event(struct perf_session *session, union | |||
986 | } | 1034 | } |
987 | } | 1035 | } |
988 | 1036 | ||
1037 | static void event_swap(union perf_event *event, bool sample_id_all) | ||
1038 | { | ||
1039 | perf_event__swap_op swap; | ||
1040 | |||
1041 | swap = perf_event__swap_ops[event->header.type]; | ||
1042 | if (swap) | ||
1043 | swap(event, sample_id_all); | ||
1044 | } | ||
1045 | |||
989 | static int perf_session__process_event(struct perf_session *session, | 1046 | static int perf_session__process_event(struct perf_session *session, |
990 | union perf_event *event, | 1047 | union perf_event *event, |
991 | struct perf_tool *tool, | 1048 | struct perf_tool *tool, |
@@ -994,9 +1051,8 @@ static int perf_session__process_event(struct perf_session *session, | |||
994 | struct perf_sample sample; | 1051 | struct perf_sample sample; |
995 | int ret; | 1052 | int ret; |
996 | 1053 | ||
997 | if (session->header.needs_swap && | 1054 | if (session->header.needs_swap) |
998 | perf_event__swap_ops[event->header.type]) | 1055 | event_swap(event, session->sample_id_all); |
999 | perf_event__swap_ops[event->header.type](event); | ||
1000 | 1056 | ||
1001 | if (event->header.type >= PERF_RECORD_HEADER_MAX) | 1057 | if (event->header.type >= PERF_RECORD_HEADER_MAX) |
1002 | return -EINVAL; | 1058 | return -EINVAL; |
@@ -1428,7 +1484,6 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, | |||
1428 | int print_sym, int print_dso, int print_symoffset) | 1484 | int print_sym, int print_dso, int print_symoffset) |
1429 | { | 1485 | { |
1430 | struct addr_location al; | 1486 | struct addr_location al; |
1431 | struct callchain_cursor *cursor = &evsel->hists.callchain_cursor; | ||
1432 | struct callchain_cursor_node *node; | 1487 | struct callchain_cursor_node *node; |
1433 | 1488 | ||
1434 | if (perf_event__preprocess_sample(event, machine, &al, sample, | 1489 | if (perf_event__preprocess_sample(event, machine, &al, sample, |
@@ -1446,10 +1501,10 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, | |||
1446 | error("Failed to resolve callchain. Skipping\n"); | 1501 | error("Failed to resolve callchain. Skipping\n"); |
1447 | return; | 1502 | return; |
1448 | } | 1503 | } |
1449 | callchain_cursor_commit(cursor); | 1504 | callchain_cursor_commit(&callchain_cursor); |
1450 | 1505 | ||
1451 | while (1) { | 1506 | while (1) { |
1452 | node = callchain_cursor_current(cursor); | 1507 | node = callchain_cursor_current(&callchain_cursor); |
1453 | if (!node) | 1508 | if (!node) |
1454 | break; | 1509 | break; |
1455 | 1510 | ||
@@ -1460,12 +1515,12 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, | |||
1460 | } | 1515 | } |
1461 | if (print_dso) { | 1516 | if (print_dso) { |
1462 | printf(" ("); | 1517 | printf(" ("); |
1463 | map__fprintf_dsoname(al.map, stdout); | 1518 | map__fprintf_dsoname(node->map, stdout); |
1464 | printf(")"); | 1519 | printf(")"); |
1465 | } | 1520 | } |
1466 | printf("\n"); | 1521 | printf("\n"); |
1467 | 1522 | ||
1468 | callchain_cursor_advance(cursor); | 1523 | callchain_cursor_advance(&callchain_cursor); |
1469 | } | 1524 | } |
1470 | 1525 | ||
1471 | } else { | 1526 | } else { |