diff options
Diffstat (limited to 'tools/perf/util/session.c')
| -rw-r--r-- | tools/perf/util/session.c | 109 |
1 files changed, 87 insertions, 22 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 93d355d27109..56142d0fb8d7 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, |
| @@ -868,7 +926,7 @@ static struct machine * | |||
| 868 | else | 926 | else |
| 869 | pid = event->ip.pid; | 927 | pid = event->ip.pid; |
| 870 | 928 | ||
| 871 | return perf_session__find_machine(session, pid); | 929 | return perf_session__findnew_machine(session, pid); |
| 872 | } | 930 | } |
| 873 | 931 | ||
| 874 | return perf_session__find_host_machine(session); | 932 | return perf_session__find_host_machine(session); |
| @@ -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 { |
