aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-01-14 09:23:10 -0500
committerIngo Molnar <mingo@elte.hu>2010-01-16 04:58:45 -0500
commitba21594cddee0a3af582971656702b1c4509d8f5 (patch)
tree2526e75ba7479a5fd59f979962f1937c3104ad99
parent0d755034dbd01e240eadf2d31f4f75d3088ccd21 (diff)
perf tools: Cross platform perf.data analysis support
There are still some problems related to loading vmlinux files, but those are unrelated to the feature implemented in this patch, so will get fixed in the next patches, but here are some results: 1. collect perf.data file on a Fedora 12 machine, x86_64, 64-bit userland 2. transfer it to a Debian Testing machine, PARISC64, 32-bit userland acme@parisc:~/git/linux-2.6-tip$ perf buildid-list | head -5 74f9930ee94475b6b3238caf3725a50d59cb994b [kernel.kallsyms] 55fdd56670453ea66c011158c4b9d30179c1d049 /lib/modules/2.6.33-rc4-tip+/kernel/net/ipv4/netfilter/ipt_MASQUERADE.ko 41adff63c730890480980d5d8ba513f1c216a858 /lib/modules/2.6.33-rc4-tip+/kernel/net/ipv4/netfilter/iptable_nat.ko 90a33def1077bb8e97b8a78546dc96c2de62df46 /lib/modules/2.6.33-rc4-tip+/kernel/net/ipv4/netfilter/nf_nat.ko 984c7bea90ce1376d5c8e7ef43a781801286e62d /lib/modules/2.6.33-rc4-tip+/kernel/drivers/net/tun.ko acme@parisc:~/git/linux-2.6-tip$ perf buildid-list | tail -5 22492f3753c6a67de5c7ccbd6b863390c92c0723 /usr/lib64/libXt.so.6.0.0 353802bb7e1b895ba43507cc678f951e778e4c6f /usr/lib64/libMagickCore.so.2.0.0 d10c2897558595efe7be8b0584cf7e6398bc776c /usr/lib64/libfprint.so.0.0.0 a83ecfb519a788774a84d5ddde633c9ba56c03ab /home/acme/bin/perf d3ca765a8ecf257d263801d7ad8c49c189082317 /usr/lib64/libdwarf.so.0.0 acme@parisc:~/git/linux-2.6-tip$ acme@parisc:~/git/linux-2.6-tip$ perf report --sort comm The file [kernel.kallsyms] cannot be used, trying to use /proc/kallsyms... ^^^^ The problem related to vmlinux handling, it shouldn't be trying this ^^^^ rather alien /proc/kallsyms at all... /lib64/libpthread-2.10.2.so with build id 5c68f7afeb33309c78037e374b0deee84dd441f6 not found, continuing without symbols /lib64/libc-2.10.2.so with build id eb4ec8fa8b2a5eb18cad173c92f27ed8887ed1c1 not found, continuing without symbols /home/acme/bin/perf with build id a83ecfb519a788774a84d5ddde633c9ba56c03ab not found, continuing without symbols /usr/sbin/openvpn with build id f2037a091ef36b591187a858d75e203690ea9409 not found, continuing without symbols Failed to open /lib/modules/2.6.33-rc4-tip+/kernel/drivers/net/e1000e/e1000e.ko, continuing without symbols Failed to open /lib/modules/2.6.33-rc4-tip+/kernel/drivers/net/wireless/iwlwifi/iwlcore.ko, continuing without symbols <SNIP more complaints about not finding the right build-ids, those will have to wait for 'perf archive' or plain copying what was collected by 'perf record' on the x86_64, source machine, see further below for an example of this > # Samples: 293085637 # # Overhead Command # ........ ............... # 61.70% find 23.50% perf 5.86% swapper 3.12% sshd 2.39% init 0.87% bash 0.86% sleep 0.59% dbus-daemon 0.25% hald 0.24% NetworkManager 0.19% hald-addon-rfki 0.15% openvpn 0.07% phy0 0.07% events/0 0.05% iwl3945 0.05% events/1 0.03% kondemand/0 acme@parisc:~/git/linux-2.6-tip$ Which matches what we get when running the same command for the same perf.data file on the F12, x86_64, source machine: [root@doppio linux-2.6-tip]# perf report --sort comm # Samples: 293085637 # # Overhead Command # ........ ............... # 61.70% find 23.50% perf 5.86% swapper 3.12% sshd 2.39% init 0.87% bash 0.86% sleep 0.59% dbus-daemon 0.25% hald 0.24% NetworkManager 0.19% hald-addon-rfki 0.15% openvpn 0.07% phy0 0.07% events/0 0.05% iwl3945 0.05% events/1 0.03% kondemand/0 [root@doppio linux-2.6-tip]# The other modes work as well, modulo the problem with vmlinux: acme@parisc:~/git/linux-2.6-tip$ perf report --sort comm,dso 2> /dev/null | head -15 # Samples: 293085637 # # Overhead Command Shared Object # ........ ............... ................................. # 35.11% find ffffffff81002b5a 18.25% perf ffffffff8102235f 16.17% find libc-2.10.2.so 9.07% find find 5.80% swapper ffffffff8102235f 3.95% perf libc-2.10.2.so 2.33% init ffffffff810091b9 1.65% sshd libcrypto.so.0.9.8k 1.35% find [e1000e] 0.68% sleep libc-2.10.2.so acme@parisc:~/git/linux-2.6-tip$ And the lack of the right buildids: acme@parisc:~/git/linux-2.6-tip$ perf report --sort comm,dso,symbol 2> /dev/null | head -15 # Samples: 293085637 # # Overhead Command Shared Object Symbol # ........ ............... ................................. ...... # 35.11% find ffffffff81002b5a [k] 0xffffffff81002b5a 18.25% perf ffffffff8102235f [k] 0xffffffff8102235f 16.17% find libc-2.10.2.so [.] 0x00000000045782 9.07% find find [.] 0x0000000000fb0e 5.80% swapper ffffffff8102235f [k] 0xffffffff8102235f 3.95% perf libc-2.10.2.so [.] 0x0000000007f398 2.33% init ffffffff810091b9 [k] 0xffffffff810091b9 1.65% sshd libcrypto.so.0.9.8k [.] 0x00000000105440 1.35% find [e1000e] [k] 0x00000000010948 0.68% sleep libc-2.10.2.so [.] 0x0000000011ad5b acme@parisc:~/git/linux-2.6-tip$ But if we: acme@parisc:~/git/linux-2.6-tip$ ls ~/.debug ls: cannot access /home/acme/.debug: No such file or directory acme@parisc:~/git/linux-2.6-tip$ mkdir -p ~/.debug/lib64/libc-2.10.2.so/ acme@parisc:~/git/linux-2.6-tip$ scp doppio:.debug/lib64/libc-2.10.2.so/* ~/.debug/lib64/libc-2.10.2.so/ acme@doppio's password: eb4ec8fa8b2a5eb18cad173c92f27ed8887ed1c1 100% 1783KB 714.7KB/s 00:02 acme@parisc:~/git/linux-2.6-tip$ mkdir -p ~/.debug/.build-id/eb acme@parisc:~/git/linux-2.6-tip$ ln -s ../../lib64/libc-2.10.2.so/eb4ec8fa8b2a5eb18cad173c92f27ed8887ed1c1 ~/.debug/.build-id/eb/4ec8fa8b2a5eb18cad173c92f27ed8887ed1c1 acme@parisc:~/git/linux-2.6-tip$ perf report --dsos libc-2.10.2.so 2> /dev/null # dso: libc-2.10.2.so # Samples: 64281170 # # Overhead Command Symbol # ........ ............... ...... # 14.98% perf [.] __GI_strcmp 12.30% find [.] __GI_memmove 9.25% find [.] _int_malloc 7.60% find [.] _IO_vfprintf_internal 6.10% find [.] _IO_new_file_xsputn 6.02% find [.] __GI_close 3.08% find [.] _IO_file_overflow_internal 3.08% find [.] malloc_consolidate 3.08% find [.] _int_free 3.08% find [.] __strchrnul 3.08% find [.] __getdents64 3.08% find [.] __write_nocancel 3.08% sleep [.] __GI__dl_addr 3.08% sshd [.] __libc_select 3.08% find [.] _IO_new_file_write 3.07% find [.] _IO_new_do_write 3.06% find [.] __GI___errno_location 3.05% find [.] __GI___libc_malloc 3.04% perf [.] __GI_memcpy 1.71% find [.] __fprintf_chk 1.29% bash [.] __gconv_transform_utf8_internal 0.79% dbus-daemon [.] __GI_strlen # # (For a higher level overview, try: perf report --sort comm,dso) # acme@parisc:~/git/linux-2.6-tip$ Which matches what we get on the source, F12, x86_64 machine: [root@doppio linux-2.6-tip]# perf report --dsos libc-2.10.2.so # dso: libc-2.10.2.so # Samples: 64281170 # # Overhead Command Symbol # ........ ............... ...... # 14.98% perf [.] __GI_strcmp 12.30% find [.] __GI_memmove 9.25% find [.] _int_malloc 7.60% find [.] _IO_vfprintf_internal 6.10% find [.] _IO_new_file_xsputn 6.02% find [.] __GI_close 3.08% find [.] _IO_file_overflow_internal 3.08% find [.] malloc_consolidate 3.08% find [.] _int_free 3.08% find [.] __strchrnul 3.08% find [.] __getdents64 3.08% find [.] __write_nocancel 3.08% sleep [.] __GI__dl_addr 3.08% sshd [.] __libc_select 3.08% find [.] _IO_new_file_write 3.07% find [.] _IO_new_do_write 3.06% find [.] __GI___errno_location 3.05% find [.] __GI___libc_malloc 3.04% perf [.] __GI_memcpy 1.71% find [.] __fprintf_chk 1.29% bash [.] __gconv_transform_utf8_internal 0.79% dbus-daemon [.] __GI_strlen # # (For a higher level overview, try: perf report --sort comm,dso) # [root@doppio linux-2.6-tip]# So I think this is really, really nice in that it demonstrates the portability of perf.data files and the use of build-ids accross such aliens worlds :-) There are some things to fix tho, like the bitmap on the header, but things are looking good. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1263478990-8200-2-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--tools/perf/util/header.c63
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/session.c108
-rw-r--r--tools/perf/util/session.h7
4 files changed, 157 insertions, 23 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ec96321eb9e4..b31e0ae4b8db 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1,8 +1,10 @@
1#include <sys/types.h> 1#include <sys/types.h>
2#include <byteswap.h>
2#include <unistd.h> 3#include <unistd.h>
3#include <stdio.h> 4#include <stdio.h>
4#include <stdlib.h> 5#include <stdlib.h>
5#include <linux/list.h> 6#include <linux/list.h>
7#include <linux/kernel.h>
6 8
7#include "util.h" 9#include "util.h"
8#include "header.h" 10#include "header.h"
@@ -464,8 +466,21 @@ static int do_read(int fd, void *buf, size_t size)
464 return 0; 466 return 0;
465} 467}
466 468
469static int perf_header__getbuffer64(struct perf_header *self,
470 int fd, void *buf, size_t size)
471{
472 if (do_read(fd, buf, size))
473 return -1;
474
475 if (self->needs_swap)
476 mem_bswap_64(buf, size);
477
478 return 0;
479}
480
467int perf_header__process_sections(struct perf_header *self, int fd, 481int perf_header__process_sections(struct perf_header *self, int fd,
468 int (*process)(struct perf_file_section *self, 482 int (*process)(struct perf_file_section *self,
483 struct perf_header *ph,
469 int feat, int fd)) 484 int feat, int fd))
470{ 485{
471 struct perf_file_section *feat_sec; 486 struct perf_file_section *feat_sec;
@@ -486,7 +501,7 @@ int perf_header__process_sections(struct perf_header *self, int fd,
486 501
487 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 502 lseek(fd, self->data_offset + self->data_size, SEEK_SET);
488 503
489 if (do_read(fd, feat_sec, sec_size)) 504 if (perf_header__getbuffer64(self, fd, feat_sec, sec_size))
490 goto out_free; 505 goto out_free;
491 506
492 err = 0; 507 err = 0;
@@ -494,7 +509,7 @@ int perf_header__process_sections(struct perf_header *self, int fd,
494 if (perf_header__has_feat(self, feat)) { 509 if (perf_header__has_feat(self, feat)) {
495 struct perf_file_section *sec = &feat_sec[idx++]; 510 struct perf_file_section *sec = &feat_sec[idx++];
496 511
497 err = process(sec, feat, fd); 512 err = process(sec, self, feat, fd);
498 if (err < 0) 513 if (err < 0)
499 break; 514 break;
500 } 515 }
@@ -511,10 +526,20 @@ int perf_file_header__read(struct perf_file_header *self,
511 lseek(fd, 0, SEEK_SET); 526 lseek(fd, 0, SEEK_SET);
512 527
513 if (do_read(fd, self, sizeof(*self)) || 528 if (do_read(fd, self, sizeof(*self)) ||
514 self->magic != PERF_MAGIC || 529 memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
515 self->attr_size != sizeof(struct perf_file_attr))
516 return -1; 530 return -1;
517 531
532 if (self->attr_size != sizeof(struct perf_file_attr)) {
533 u64 attr_size = bswap_64(self->attr_size);
534
535 if (attr_size != sizeof(struct perf_file_attr))
536 return -1;
537
538 mem_bswap_64(self, offsetof(struct perf_file_header,
539 adds_features));
540 ph->needs_swap = true;
541 }
542
518 if (self->size != sizeof(*self)) { 543 if (self->size != sizeof(*self)) {
519 /* Support the previous format */ 544 /* Support the previous format */
520 if (self->size == offsetof(typeof(*self), adds_features)) 545 if (self->size == offsetof(typeof(*self), adds_features))
@@ -524,16 +549,28 @@ int perf_file_header__read(struct perf_file_header *self,
524 } 549 }
525 550
526 memcpy(&ph->adds_features, &self->adds_features, 551 memcpy(&ph->adds_features, &self->adds_features,
527 sizeof(self->adds_features)); 552 sizeof(ph->adds_features));
553 /*
554 * FIXME: hack that assumes that if we need swap the perf.data file
555 * may be coming from an arch with a different word-size, ergo different
556 * DEFINE_BITMAP format, investigate more later, but for now its mostly
557 * safe to assume that we have a build-id section. Trace files probably
558 * have several other issues in this realm anyway...
559 */
560 if (ph->needs_swap) {
561 memset(&ph->adds_features, 0, sizeof(ph->adds_features));
562 perf_header__set_feat(ph, HEADER_BUILD_ID);
563 }
528 564
529 ph->event_offset = self->event_types.offset; 565 ph->event_offset = self->event_types.offset;
530 ph->event_size = self->event_types.size; 566 ph->event_size = self->event_types.size;
531 ph->data_offset = self->data.offset; 567 ph->data_offset = self->data.offset;
532 ph->data_size = self->data.size; 568 ph->data_size = self->data.size;
533 return 0; 569 return 0;
534} 570}
535 571
536static int perf_file_section__process(struct perf_file_section *self, 572static int perf_file_section__process(struct perf_file_section *self,
573 struct perf_header *ph,
537 int feat, int fd) 574 int feat, int fd)
538{ 575{
539 if (lseek(fd, self->offset, SEEK_SET) < 0) { 576 if (lseek(fd, self->offset, SEEK_SET) < 0) {
@@ -548,7 +585,7 @@ static int perf_file_section__process(struct perf_file_section *self,
548 break; 585 break;
549 586
550 case HEADER_BUILD_ID: 587 case HEADER_BUILD_ID:
551 if (perf_header__read_build_ids(fd, self->offset, self->size)) 588 if (perf_header__read_build_ids(ph, fd, self->offset, self->size))
552 pr_debug("Failed to read buildids, continuing...\n"); 589 pr_debug("Failed to read buildids, continuing...\n");
553 break; 590 break;
554 default: 591 default:
@@ -560,7 +597,7 @@ static int perf_file_section__process(struct perf_file_section *self,
560 597
561int perf_header__read(struct perf_header *self, int fd) 598int perf_header__read(struct perf_header *self, int fd)
562{ 599{
563 struct perf_file_header f_header; 600 struct perf_file_header f_header;
564 struct perf_file_attr f_attr; 601 struct perf_file_attr f_attr;
565 u64 f_id; 602 u64 f_id;
566 int nr_attrs, nr_ids, i, j; 603 int nr_attrs, nr_ids, i, j;
@@ -577,8 +614,9 @@ int perf_header__read(struct perf_header *self, int fd)
577 struct perf_header_attr *attr; 614 struct perf_header_attr *attr;
578 off_t tmp; 615 off_t tmp;
579 616
580 if (do_read(fd, &f_attr, sizeof(f_attr))) 617 if (perf_header__getbuffer64(self, fd, &f_attr, sizeof(f_attr)))
581 goto out_errno; 618 goto out_errno;
619
582 tmp = lseek(fd, 0, SEEK_CUR); 620 tmp = lseek(fd, 0, SEEK_CUR);
583 621
584 attr = perf_header_attr__new(&f_attr.attr); 622 attr = perf_header_attr__new(&f_attr.attr);
@@ -589,7 +627,7 @@ int perf_header__read(struct perf_header *self, int fd)
589 lseek(fd, f_attr.ids.offset, SEEK_SET); 627 lseek(fd, f_attr.ids.offset, SEEK_SET);
590 628
591 for (j = 0; j < nr_ids; j++) { 629 for (j = 0; j < nr_ids; j++) {
592 if (do_read(fd, &f_id, sizeof(f_id))) 630 if (perf_header__getbuffer64(self, fd, &f_id, sizeof(f_id)))
593 goto out_errno; 631 goto out_errno;
594 632
595 if (perf_header_attr__add_id(attr, f_id) < 0) { 633 if (perf_header_attr__add_id(attr, f_id) < 0) {
@@ -610,7 +648,8 @@ int perf_header__read(struct perf_header *self, int fd)
610 events = malloc(f_header.event_types.size); 648 events = malloc(f_header.event_types.size);
611 if (events == NULL) 649 if (events == NULL)
612 return -ENOMEM; 650 return -ENOMEM;
613 if (do_read(fd, events, f_header.event_types.size)) 651 if (perf_header__getbuffer64(self, fd, events,
652 f_header.event_types.size))
614 goto out_errno; 653 goto out_errno;
615 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 654 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
616 } 655 }
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 2b69aab67e35..ccc8540feccd 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -52,6 +52,7 @@ struct perf_header {
52 u64 data_size; 52 u64 data_size;
53 u64 event_offset; 53 u64 event_offset;
54 u64 event_size; 54 u64 event_size;
55 bool needs_swap;
55 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); 56 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
56}; 57};
57 58
@@ -80,6 +81,7 @@ bool perf_header__has_feat(const struct perf_header *self, int feat);
80 81
81int perf_header__process_sections(struct perf_header *self, int fd, 82int perf_header__process_sections(struct perf_header *self, int fd,
82 int (*process)(struct perf_file_section *self, 83 int (*process)(struct perf_file_section *self,
84 struct perf_header *ph,
83 int feat, int fd)); 85 int feat, int fd));
84 86
85#endif /* __PERF_HEADER_H */ 87#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index e3ccdb46d6c4..604e14f6a6f9 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1,5 +1,6 @@
1#include <linux/kernel.h> 1#include <linux/kernel.h>
2 2
3#include <byteswap.h>
3#include <unistd.h> 4#include <unistd.h>
4#include <sys/types.h> 5#include <sys/types.h>
5 6
@@ -201,21 +202,88 @@ void event__print_totals(void)
201 event__name[i], event__total[i]); 202 event__name[i], event__total[i]);
202} 203}
203 204
205void mem_bswap_64(void *src, int byte_size)
206{
207 u64 *m = src;
208
209 while (byte_size > 0) {
210 *m = bswap_64(*m);
211 byte_size -= sizeof(u64);
212 ++m;
213 }
214}
215
216static void event__all64_swap(event_t *self)
217{
218 struct perf_event_header *hdr = &self->header;
219 mem_bswap_64(hdr + 1, self->header.size - sizeof(*hdr));
220}
221
222static void event__comm_swap(event_t *self)
223{
224 self->comm.pid = bswap_32(self->comm.pid);
225 self->comm.tid = bswap_32(self->comm.tid);
226}
227
228static void event__mmap_swap(event_t *self)
229{
230 self->mmap.pid = bswap_32(self->mmap.pid);
231 self->mmap.tid = bswap_32(self->mmap.tid);
232 self->mmap.start = bswap_64(self->mmap.start);
233 self->mmap.len = bswap_64(self->mmap.len);
234 self->mmap.pgoff = bswap_64(self->mmap.pgoff);
235}
236
237static void event__task_swap(event_t *self)
238{
239 self->fork.pid = bswap_32(self->fork.pid);
240 self->fork.tid = bswap_32(self->fork.tid);
241 self->fork.ppid = bswap_32(self->fork.ppid);
242 self->fork.ptid = bswap_32(self->fork.ptid);
243 self->fork.time = bswap_64(self->fork.time);
244}
245
246static void event__read_swap(event_t *self)
247{
248 self->read.pid = bswap_32(self->read.pid);
249 self->read.tid = bswap_32(self->read.tid);
250 self->read.value = bswap_64(self->read.value);
251 self->read.time_enabled = bswap_64(self->read.time_enabled);
252 self->read.time_running = bswap_64(self->read.time_running);
253 self->read.id = bswap_64(self->read.id);
254}
255
256typedef void (*event__swap_op)(event_t *self);
257
258static event__swap_op event__swap_ops[] = {
259 [PERF_RECORD_MMAP] = event__mmap_swap,
260 [PERF_RECORD_COMM] = event__comm_swap,
261 [PERF_RECORD_FORK] = event__task_swap,
262 [PERF_RECORD_EXIT] = event__task_swap,
263 [PERF_RECORD_LOST] = event__all64_swap,
264 [PERF_RECORD_READ] = event__read_swap,
265 [PERF_RECORD_SAMPLE] = event__all64_swap,
266 [PERF_RECORD_MAX] = NULL,
267};
268
204static int perf_session__process_event(struct perf_session *self, 269static int perf_session__process_event(struct perf_session *self,
205 event_t *event, 270 event_t *event,
206 struct perf_event_ops *ops, 271 struct perf_event_ops *ops,
207 unsigned long offset, unsigned long head) 272 u64 offset, u64 head)
208{ 273{
209 trace_event(event); 274 trace_event(event);
210 275
211 if (event->header.type < PERF_RECORD_MAX) { 276 if (event->header.type < PERF_RECORD_MAX) {
212 dump_printf("%#lx [%#x]: PERF_RECORD_%s", 277 dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
213 offset + head, event->header.size, 278 offset + head, event->header.size,
214 event__name[event->header.type]); 279 event__name[event->header.type]);
215 ++event__total[0]; 280 ++event__total[0];
216 ++event__total[event->header.type]; 281 ++event__total[event->header.type];
217 } 282 }
218 283
284 if (self->header.needs_swap && event__swap_ops[event->header.type])
285 event__swap_ops[event->header.type](event);
286
219 switch (event->header.type) { 287 switch (event->header.type) {
220 case PERF_RECORD_SAMPLE: 288 case PERF_RECORD_SAMPLE:
221 return ops->sample(event, self); 289 return ops->sample(event, self);
@@ -241,7 +309,15 @@ static int perf_session__process_event(struct perf_session *self,
241 } 309 }
242} 310}
243 311
244int perf_header__read_build_ids(int input, u64 offset, u64 size) 312void perf_event_header__bswap(struct perf_event_header *self)
313{
314 self->type = bswap_32(self->type);
315 self->misc = bswap_16(self->misc);
316 self->size = bswap_16(self->size);
317}
318
319int perf_header__read_build_ids(struct perf_header *self,
320 int input, u64 offset, u64 size)
245{ 321{
246 struct build_id_event bev; 322 struct build_id_event bev;
247 char filename[PATH_MAX]; 323 char filename[PATH_MAX];
@@ -256,6 +332,9 @@ int perf_header__read_build_ids(int input, u64 offset, u64 size)
256 if (read(input, &bev, sizeof(bev)) != sizeof(bev)) 332 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
257 goto out; 333 goto out;
258 334
335 if (self->needs_swap)
336 perf_event_header__bswap(&bev.header);
337
259 len = bev.header.size - sizeof(bev); 338 len = bev.header.size - sizeof(bev);
260 if (read(input, filename, len) != len) 339 if (read(input, filename, len) != len)
261 goto out; 340 goto out;
@@ -292,9 +371,9 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
292int perf_session__process_events(struct perf_session *self, 371int perf_session__process_events(struct perf_session *self,
293 struct perf_event_ops *ops) 372 struct perf_event_ops *ops)
294{ 373{
295 int err; 374 int err, mmap_prot, mmap_flags;
296 unsigned long head, shift; 375 u64 head, shift;
297 unsigned long offset = 0; 376 u64 offset = 0;
298 size_t page_size; 377 size_t page_size;
299 event_t *event; 378 event_t *event;
300 uint32_t size; 379 uint32_t size;
@@ -330,9 +409,16 @@ out_getcwd_err:
330 offset += shift; 409 offset += shift;
331 head -= shift; 410 head -= shift;
332 411
412 mmap_prot = PROT_READ;
413 mmap_flags = MAP_SHARED;
414
415 if (self->header.needs_swap) {
416 mmap_prot |= PROT_WRITE;
417 mmap_flags = MAP_PRIVATE;
418 }
333remap: 419remap:
334 buf = mmap(NULL, page_size * self->mmap_window, PROT_READ, 420 buf = mmap(NULL, page_size * self->mmap_window, mmap_prot,
335 MAP_SHARED, self->fd, offset); 421 mmap_flags, self->fd, offset);
336 if (buf == MAP_FAILED) { 422 if (buf == MAP_FAILED) {
337 pr_err("failed to mmap file\n"); 423 pr_err("failed to mmap file\n");
338 err = -errno; 424 err = -errno;
@@ -342,6 +428,8 @@ remap:
342more: 428more:
343 event = (event_t *)(buf + head); 429 event = (event_t *)(buf + head);
344 430
431 if (self->header.needs_swap)
432 perf_event_header__bswap(&event->header);
345 size = event->header.size; 433 size = event->header.size;
346 if (size == 0) 434 if (size == 0)
347 size = 8; 435 size = 8;
@@ -361,12 +449,12 @@ more:
361 449
362 size = event->header.size; 450 size = event->header.size;
363 451
364 dump_printf("\n%#lx [%#x]: event: %d\n", 452 dump_printf("\n%#Lx [%#x]: event: %d\n",
365 offset + head, event->header.size, event->header.type); 453 offset + head, event->header.size, event->header.type);
366 454
367 if (size == 0 || 455 if (size == 0 ||
368 perf_session__process_event(self, event, ops, offset, head) < 0) { 456 perf_session__process_event(self, event, ops, offset, head) < 0) {
369 dump_printf("%#lx [%#x]: skipping unknown header type: %d\n", 457 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n",
370 offset + head, event->header.size, 458 offset + head, event->header.size,
371 event->header.type); 459 event->header.type);
372 /* 460 /*
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index d4a9d20f8d44..36d1a80c0b6c 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -51,6 +51,8 @@ struct perf_event_ops {
51struct perf_session *perf_session__new(const char *filename, int mode, bool force); 51struct perf_session *perf_session__new(const char *filename, int mode, bool force);
52void perf_session__delete(struct perf_session *self); 52void perf_session__delete(struct perf_session *self);
53 53
54void perf_event_header__bswap(struct perf_event_header *self);
55
54int perf_session__process_events(struct perf_session *self, 56int perf_session__process_events(struct perf_session *self,
55 struct perf_event_ops *event_ops); 57 struct perf_event_ops *event_ops);
56 58
@@ -61,7 +63,8 @@ struct symbol **perf_session__resolve_callchain(struct perf_session *self,
61 63
62bool perf_session__has_traces(struct perf_session *self, const char *msg); 64bool perf_session__has_traces(struct perf_session *self, const char *msg);
63 65
64int perf_header__read_build_ids(int input, u64 offset, u64 file_size); 66int perf_header__read_build_ids(struct perf_header *self, int input,
67 u64 offset, u64 file_size);
65 68
66int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self, 69int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self,
67 const char *symbol_name, 70 const char *symbol_name,
@@ -69,4 +72,6 @@ int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self,
69void perf_session__reloc_vmlinux_maps(struct perf_session *self, 72void perf_session__reloc_vmlinux_maps(struct perf_session *self,
70 u64 unrelocated_addr); 73 u64 unrelocated_addr);
71 74
75void mem_bswap_64(void *src, int byte_size);
76
72#endif /* __PERF_SESSION_H */ 77#endif /* __PERF_SESSION_H */