summaryrefslogtreecommitdiffstats
path: root/tools/perf/util/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r--tools/perf/util/session.c108
1 files changed, 98 insertions, 10 deletions
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 @@
#include <linux/kernel.h>
+#include <byteswap.h>
#include <unistd.h>
#include <sys/types.h>
@@ -201,21 +202,88 @@ void event__print_totals(void)
event__name[i], event__total[i]);
}
+void mem_bswap_64(void *src, int byte_size)
+{
+ u64 *m = src;
+
+ while (byte_size > 0) {
+ *m = bswap_64(*m);
+ byte_size -= sizeof(u64);
+ ++m;
+ }
+}
+
+static void event__all64_swap(event_t *self)
+{
+ struct perf_event_header *hdr = &self->header;
+ mem_bswap_64(hdr + 1, self->header.size - sizeof(*hdr));
+}
+
+static void event__comm_swap(event_t *self)
+{
+ self->comm.pid = bswap_32(self->comm.pid);
+ self->comm.tid = bswap_32(self->comm.tid);
+}
+
+static void event__mmap_swap(event_t *self)
+{
+ self->mmap.pid = bswap_32(self->mmap.pid);
+ self->mmap.tid = bswap_32(self->mmap.tid);
+ self->mmap.start = bswap_64(self->mmap.start);
+ self->mmap.len = bswap_64(self->mmap.len);
+ self->mmap.pgoff = bswap_64(self->mmap.pgoff);
+}
+
+static void event__task_swap(event_t *self)
+{
+ self->fork.pid = bswap_32(self->fork.pid);
+ self->fork.tid = bswap_32(self->fork.tid);
+ self->fork.ppid = bswap_32(self->fork.ppid);
+ self->fork.ptid = bswap_32(self->fork.ptid);
+ self->fork.time = bswap_64(self->fork.time);
+}
+
+static void event__read_swap(event_t *self)
+{
+ self->read.pid = bswap_32(self->read.pid);
+ self->read.tid = bswap_32(self->read.tid);
+ self->read.value = bswap_64(self->read.value);
+ self->read.time_enabled = bswap_64(self->read.time_enabled);
+ self->read.time_running = bswap_64(self->read.time_running);
+ self->read.id = bswap_64(self->read.id);
+}
+
+typedef void (*event__swap_op)(event_t *self);
+
+static event__swap_op event__swap_ops[] = {
+ [PERF_RECORD_MMAP] = event__mmap_swap,
+ [PERF_RECORD_COMM] = event__comm_swap,
+ [PERF_RECORD_FORK] = event__task_swap,
+ [PERF_RECORD_EXIT] = event__task_swap,
+ [PERF_RECORD_LOST] = event__all64_swap,
+ [PERF_RECORD_READ] = event__read_swap,
+ [PERF_RECORD_SAMPLE] = event__all64_swap,
+ [PERF_RECORD_MAX] = NULL,
+};
+
static int perf_session__process_event(struct perf_session *self,
event_t *event,
struct perf_event_ops *ops,
- unsigned long offset, unsigned long head)
+ u64 offset, u64 head)
{
trace_event(event);
if (event->header.type < PERF_RECORD_MAX) {
- dump_printf("%#lx [%#x]: PERF_RECORD_%s",
+ dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
offset + head, event->header.size,
event__name[event->header.type]);
++event__total[0];
++event__total[event->header.type];
}
+ if (self->header.needs_swap && event__swap_ops[event->header.type])
+ event__swap_ops[event->header.type](event);
+
switch (event->header.type) {
case PERF_RECORD_SAMPLE:
return ops->sample(event, self);
@@ -241,7 +309,15 @@ static int perf_session__process_event(struct perf_session *self,
}
}
-int perf_header__read_build_ids(int input, u64 offset, u64 size)
+void perf_event_header__bswap(struct perf_event_header *self)
+{
+ self->type = bswap_32(self->type);
+ self->misc = bswap_16(self->misc);
+ self->size = bswap_16(self->size);
+}
+
+int perf_header__read_build_ids(struct perf_header *self,
+ int input, u64 offset, u64 size)
{
struct build_id_event bev;
char filename[PATH_MAX];
@@ -256,6 +332,9 @@ int perf_header__read_build_ids(int input, u64 offset, u64 size)
if (read(input, &bev, sizeof(bev)) != sizeof(bev))
goto out;
+ if (self->needs_swap)
+ perf_event_header__bswap(&bev.header);
+
len = bev.header.size - sizeof(bev);
if (read(input, filename, len) != len)
goto out;
@@ -292,9 +371,9 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
int perf_session__process_events(struct perf_session *self,
struct perf_event_ops *ops)
{
- int err;
- unsigned long head, shift;
- unsigned long offset = 0;
+ int err, mmap_prot, mmap_flags;
+ u64 head, shift;
+ u64 offset = 0;
size_t page_size;
event_t *event;
uint32_t size;
@@ -330,9 +409,16 @@ out_getcwd_err:
offset += shift;
head -= shift;
+ mmap_prot = PROT_READ;
+ mmap_flags = MAP_SHARED;
+
+ if (self->header.needs_swap) {
+ mmap_prot |= PROT_WRITE;
+ mmap_flags = MAP_PRIVATE;
+ }
remap:
- buf = mmap(NULL, page_size * self->mmap_window, PROT_READ,
- MAP_SHARED, self->fd, offset);
+ buf = mmap(NULL, page_size * self->mmap_window, mmap_prot,
+ mmap_flags, self->fd, offset);
if (buf == MAP_FAILED) {
pr_err("failed to mmap file\n");
err = -errno;
@@ -342,6 +428,8 @@ remap:
more:
event = (event_t *)(buf + head);
+ if (self->header.needs_swap)
+ perf_event_header__bswap(&event->header);
size = event->header.size;
if (size == 0)
size = 8;
@@ -361,12 +449,12 @@ more:
size = event->header.size;
- dump_printf("\n%#lx [%#x]: event: %d\n",
+ dump_printf("\n%#Lx [%#x]: event: %d\n",
offset + head, event->header.size, event->header.type);
if (size == 0 ||
perf_session__process_event(self, event, ops, offset, head) < 0) {
- dump_printf("%#lx [%#x]: skipping unknown header type: %d\n",
+ dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n",
offset + head, event->header.size,
event->header.type);
/*
OpenPOWER on IntegriCloud