aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@redhat.com>2012-05-30 08:23:43 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-05-31 10:58:14 -0400
commit268fb20f832e1eb4afd5113ee31fef9332986b13 (patch)
tree03f3041f04771f4945297e242311a82b561031f1 /tools
parent8db4841fc72acc58254029f050226ea5f8103854 (diff)
perf session: Handle endianity swap on sample_id_all header data
Adding endianity swapping for event header attached via sample_id_all. Currently we dont do that and it's causing wrong data to be read when running report on architecture with different endianity than the record. The perf is currently able to process 32-bit PPC samples on 32-bit and 64-bit x86. Together with other endianity patches, this change fixies perf report discrepancies on origin and target systems as described in test 1 below, e.g. following perf report diff: ... 0.12% ps [kernel.kallsyms] [k] clear_page - 0.12% awk bash [.] alloc_word_desc + 0.12% awk bash [.] yyparse 0.11% beah-rhts-task libpython2.6.so.1.0 [.] 0x5560e 0.10% perf libc-2.12.so [.] __ctype_toupper_loc - 0.09% rhts-test-runne bash [.] maybe_make_export_env + 0.09% rhts-test-runne bash [.] 0x385a0 0.09% ps [kernel.kallsyms] [k] page_fault ... Note, running following to test perf endianity handling: test 1) - origin system: # perf record -a -- sleep 10 (any perf record will do) # perf report > report.origin # perf archive perf.data - copy the perf.data, report.origin and perf.data.tar.bz2 to a target system and run: # tar xjvf perf.data.tar.bz2 -C ~/.debug # perf report > report.target # diff -u report.origin report.target - the diff should produce no output (besides some white space stuff and possibly different date/TZ output) test 2) - origin system: # perf record -ag -fo /tmp/perf.data -- sleep 1 - mount origin system root to the target system on /mnt/origin - target system: # perf script --symfs /mnt/origin -I -i /mnt/origin/tmp/perf.data \ --kallsyms /mnt/origin/proc/kallsyms - complete perf.data header is displayed Signed-off-by: Jiri Olsa <jolsa@redhat.com> Reviewed-by: David Ahern <dsahern@gmail.com> Tested-by: David Ahern <dsahern@gmail.com> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1338380624-7443-3-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/session.c67
1 files changed, 55 insertions, 12 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 04d1e33f4592..2600916efa83 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -454,37 +454,65 @@ void mem_bswap_64(void *src, int byte_size)
454 } 454 }
455} 455}
456 456
457static void perf_event__all64_swap(union perf_event *event) 457static 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
466static void perf_event__all64_swap(union perf_event *event,
467 bool sample_id_all __used)
458{ 468{
459 struct perf_event_header *hdr = &event->header; 469 struct perf_event_header *hdr = &event->header;
460 mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); 470 mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr));
461} 471}
462 472
463static void perf_event__comm_swap(union perf_event *event) 473static void perf_event__comm_swap(union perf_event *event, bool sample_id_all)
464{ 474{
465 event->comm.pid = bswap_32(event->comm.pid); 475 event->comm.pid = bswap_32(event->comm.pid);
466 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 }
467} 484}
468 485
469static void perf_event__mmap_swap(union perf_event *event) 486static void perf_event__mmap_swap(union perf_event *event,
487 bool sample_id_all)
470{ 488{
471 event->mmap.pid = bswap_32(event->mmap.pid); 489 event->mmap.pid = bswap_32(event->mmap.pid);
472 event->mmap.tid = bswap_32(event->mmap.tid); 490 event->mmap.tid = bswap_32(event->mmap.tid);
473 event->mmap.start = bswap_64(event->mmap.start); 491 event->mmap.start = bswap_64(event->mmap.start);
474 event->mmap.len = bswap_64(event->mmap.len); 492 event->mmap.len = bswap_64(event->mmap.len);
475 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 }
476} 501}
477 502
478static void perf_event__task_swap(union perf_event *event) 503static void perf_event__task_swap(union perf_event *event, bool sample_id_all)
479{ 504{
480 event->fork.pid = bswap_32(event->fork.pid); 505 event->fork.pid = bswap_32(event->fork.pid);
481 event->fork.tid = bswap_32(event->fork.tid); 506 event->fork.tid = bswap_32(event->fork.tid);
482 event->fork.ppid = bswap_32(event->fork.ppid); 507 event->fork.ppid = bswap_32(event->fork.ppid);
483 event->fork.ptid = bswap_32(event->fork.ptid); 508 event->fork.ptid = bswap_32(event->fork.ptid);
484 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);
485} 513}
486 514
487static void perf_event__read_swap(union perf_event *event) 515static void perf_event__read_swap(union perf_event *event, bool sample_id_all)
488{ 516{
489 event->read.pid = bswap_32(event->read.pid); 517 event->read.pid = bswap_32(event->read.pid);
490 event->read.tid = bswap_32(event->read.tid); 518 event->read.tid = bswap_32(event->read.tid);
@@ -492,6 +520,9 @@ static void perf_event__read_swap(union perf_event *event)
492 event->read.time_enabled = bswap_64(event->read.time_enabled); 520 event->read.time_enabled = bswap_64(event->read.time_enabled);
493 event->read.time_running = bswap_64(event->read.time_running); 521 event->read.time_running = bswap_64(event->read.time_running);
494 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);
495} 526}
496 527
497static u8 revbyte(u8 b) 528static u8 revbyte(u8 b)
@@ -543,7 +574,8 @@ void perf_event__attr_swap(struct perf_event_attr *attr)
543 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); 574 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64));
544} 575}
545 576
546static void perf_event__hdr_attr_swap(union perf_event *event) 577static void perf_event__hdr_attr_swap(union perf_event *event,
578 bool sample_id_all __used)
547{ 579{
548 size_t size; 580 size_t size;
549 581
@@ -554,18 +586,21 @@ static void perf_event__hdr_attr_swap(union perf_event *event)
554 mem_bswap_64(event->attr.id, size); 586 mem_bswap_64(event->attr.id, size);
555} 587}
556 588
557static void perf_event__event_type_swap(union perf_event *event) 589static void perf_event__event_type_swap(union perf_event *event,
590 bool sample_id_all __used)
558{ 591{
559 event->event_type.event_type.event_id = 592 event->event_type.event_type.event_id =
560 bswap_64(event->event_type.event_type.event_id); 593 bswap_64(event->event_type.event_type.event_id);
561} 594}
562 595
563static void perf_event__tracing_data_swap(union perf_event *event) 596static void perf_event__tracing_data_swap(union perf_event *event,
597 bool sample_id_all __used)
564{ 598{
565 event->tracing_data.size = bswap_32(event->tracing_data.size); 599 event->tracing_data.size = bswap_32(event->tracing_data.size);
566} 600}
567 601
568typedef void (*perf_event__swap_op)(union perf_event *event); 602typedef void (*perf_event__swap_op)(union perf_event *event,
603 bool sample_id_all);
569 604
570static perf_event__swap_op perf_event__swap_ops[] = { 605static perf_event__swap_op perf_event__swap_ops[] = {
571 [PERF_RECORD_MMAP] = perf_event__mmap_swap, 606 [PERF_RECORD_MMAP] = perf_event__mmap_swap,
@@ -999,6 +1034,15 @@ static int perf_session__process_user_event(struct perf_session *session, union
999 } 1034 }
1000} 1035}
1001 1036
1037static 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
1002static int perf_session__process_event(struct perf_session *session, 1046static int perf_session__process_event(struct perf_session *session,
1003 union perf_event *event, 1047 union perf_event *event,
1004 struct perf_tool *tool, 1048 struct perf_tool *tool,
@@ -1007,9 +1051,8 @@ static int perf_session__process_event(struct perf_session *session,
1007 struct perf_sample sample; 1051 struct perf_sample sample;
1008 int ret; 1052 int ret;
1009 1053
1010 if (session->header.needs_swap && 1054 if (session->header.needs_swap)
1011 perf_event__swap_ops[event->header.type]) 1055 event_swap(event, session->sample_id_all);
1012 perf_event__swap_ops[event->header.type](event);
1013 1056
1014 if (event->header.type >= PERF_RECORD_HEADER_MAX) 1057 if (event->header.type >= PERF_RECORD_HEADER_MAX)
1015 return -EINVAL; 1058 return -EINVAL;