aboutsummaryrefslogtreecommitdiff
path: root/tools/perf/util/trace-event-read.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/trace-event-read.c')
-rw-r--r--tools/perf/util/trace-event-read.c539
1 files changed, 222 insertions, 317 deletions
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index f55cc3a765a..e113e180c48 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -18,8 +18,6 @@
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
-#define _FILE_OFFSET_BITS 64
-
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
@@ -33,7 +31,6 @@
#include <pthread.h>
#include <fcntl.h>
#include <unistd.h>
-#include <ctype.h>
#include <errno.h>
#include "../perf.h"
@@ -42,18 +39,10 @@
static int input_fd;
-static int read_page;
-
-int file_bigendian;
-int host_bigendian;
-static int long_size;
-
-static unsigned long page_size;
-
-static ssize_t calc_data_size;
+static ssize_t trace_data_size;
static bool repipe;
-static int do_read(int fd, void *buf, int size)
+static int __do_read(int fd, void *buf, int size)
{
int rsize = size;
@@ -66,8 +55,10 @@ static int do_read(int fd, void *buf, int size)
if (repipe) {
int retw = write(STDOUT_FILENO, buf, ret);
- if (retw <= 0 || retw != ret)
- die("repiping input file");
+ if (retw <= 0 || retw != ret) {
+ pr_debug("repiping input file");
+ return -1;
+ }
}
size -= ret;
@@ -77,17 +68,18 @@ static int do_read(int fd, void *buf, int size)
return rsize;
}
-static int read_or_die(void *data, int size)
+static int do_read(void *data, int size)
{
int r;
- r = do_read(input_fd, data, size);
- if (r <= 0)
- die("reading input file (size expected=%d received=%d)",
- size, r);
+ r = __do_read(input_fd, data, size);
+ if (r <= 0) {
+ pr_debug("reading input file (size expected=%d received=%d)",
+ size, r);
+ return -1;
+ }
- if (calc_data_size)
- calc_data_size += r;
+ trace_data_size += r;
return r;
}
@@ -100,25 +92,27 @@ static void skip(int size)
while (size) {
r = size > BUFSIZ ? BUFSIZ : size;
- read_or_die(buf, r);
+ do_read(buf, r);
size -= r;
};
}
-static unsigned int read4(void)
+static unsigned int read4(struct pevent *pevent)
{
unsigned int data;
- read_or_die(&data, 4);
- return __data2host4(data);
+ if (do_read(&data, 4) < 0)
+ return 0;
+ return __data2host4(pevent, data);
}
-static unsigned long long read8(void)
+static unsigned long long read8(struct pevent *pevent)
{
unsigned long long data;
- read_or_die(&data, 8);
- return __data2host8(data);
+ if (do_read(&data, 8) < 0)
+ return 0;
+ return __data2host8(pevent, data);
}
static char *read_string(void)
@@ -131,17 +125,23 @@ static char *read_string(void)
for (;;) {
r = read(input_fd, &c, 1);
- if (r < 0)
- die("reading input file");
+ if (r < 0) {
+ pr_debug("reading input file");
+ goto out;
+ }
- if (!r)
- die("no data");
+ if (!r) {
+ pr_debug("no data");
+ goto out;
+ }
if (repipe) {
int retw = write(STDOUT_FILENO, &c, 1);
- if (retw <= 0 || retw != r)
- die("repiping input file string");
+ if (retw <= 0 || retw != r) {
+ pr_debug("repiping input file string");
+ goto out;
+ }
}
buf[size++] = c;
@@ -150,335 +150,200 @@ static char *read_string(void)
break;
}
- if (calc_data_size)
- calc_data_size += size;
-
- str = malloc_or_die(size);
- memcpy(str, buf, size);
+ trace_data_size += size;
+ str = malloc(size);
+ if (str)
+ memcpy(str, buf, size);
+out:
return str;
}
-static void read_proc_kallsyms(void)
+static int read_proc_kallsyms(struct pevent *pevent)
{
unsigned int size;
char *buf;
- size = read4();
+ size = read4(pevent);
if (!size)
- return;
+ return 0;
+
+ buf = malloc(size + 1);
+ if (buf == NULL)
+ return -1;
- buf = malloc_or_die(size + 1);
- read_or_die(buf, size);
+ if (do_read(buf, size) < 0) {
+ free(buf);
+ return -1;
+ }
buf[size] = '\0';
- parse_proc_kallsyms(buf, size);
+ parse_proc_kallsyms(pevent, buf, size);
free(buf);
+ return 0;
}
-static void read_ftrace_printk(void)
+static int read_ftrace_printk(struct pevent *pevent)
{
unsigned int size;
char *buf;
- size = read4();
+ /* it can have 0 size */
+ size = read4(pevent);
if (!size)
- return;
+ return 0;
+
+ buf = malloc(size);
+ if (buf == NULL)
+ return -1;
- buf = malloc_or_die(size);
- read_or_die(buf, size);
+ if (do_read(buf, size) < 0) {
+ free(buf);
+ return -1;
+ }
- parse_ftrace_printk(buf, size);
+ parse_ftrace_printk(pevent, buf, size);
free(buf);
+ return 0;
}
-static void read_header_files(void)
+static int read_header_files(struct pevent *pevent)
{
unsigned long long size;
- char *header_event;
+ char *header_page;
char buf[BUFSIZ];
+ int ret = 0;
- read_or_die(buf, 12);
+ if (do_read(buf, 12) < 0)
+ return -1;
- if (memcmp(buf, "header_page", 12) != 0)
- die("did not read header page");
+ if (memcmp(buf, "header_page", 12) != 0) {
+ pr_debug("did not read header page");
+ return -1;
+ }
- size = read8();
- skip(size);
+ size = read8(pevent);
+
+ header_page = malloc(size);
+ if (header_page == NULL)
+ return -1;
- /*
- * The size field in the page is of type long,
- * use that instead, since it represents the kernel.
- */
- long_size = header_page_size_size;
+ if (do_read(header_page, size) < 0) {
+ pr_debug("did not read header page");
+ free(header_page);
+ return -1;
+ }
+
+ if (!pevent_parse_header_page(pevent, header_page, size,
+ pevent_get_long_size(pevent))) {
+ /*
+ * The commit field in the page is of type long,
+ * use that instead, since it represents the kernel.
+ */
+ pevent_set_long_size(pevent, pevent->header_page_size_size);
+ }
+ free(header_page);
- read_or_die(buf, 13);
- if (memcmp(buf, "header_event", 13) != 0)
- die("did not read header event");
+ if (do_read(buf, 13) < 0)
+ return -1;
- size = read8();
- header_event = malloc_or_die(size);
- read_or_die(header_event, size);
- free(header_event);
+ if (memcmp(buf, "header_event", 13) != 0) {
+ pr_debug("did not read header event");
+ return -1;
+ }
+
+ size = read8(pevent);
+ skip(size);
+
+ return ret;
}
-static void read_ftrace_file(unsigned long long size)
+static int read_ftrace_file(struct pevent *pevent, unsigned long long size)
{
char *buf;
- buf = malloc_or_die(size);
- read_or_die(buf, size);
- parse_ftrace_file(buf, size);
+ buf = malloc(size);
+ if (buf == NULL)
+ return -1;
+
+ if (do_read(buf, size) < 0) {
+ free(buf);
+ return -1;
+ }
+
+ parse_ftrace_file(pevent, buf, size);
free(buf);
+ return 0;
}
-static void read_event_file(char *sys, unsigned long long size)
+static int read_event_file(struct pevent *pevent, char *sys,
+ unsigned long long size)
{
char *buf;
- buf = malloc_or_die(size);
- read_or_die(buf, size);
- parse_event_file(buf, size, sys);
+ buf = malloc(size);
+ if (buf == NULL)
+ return -1;
+
+ if (do_read(buf, size) < 0) {
+ free(buf);
+ return -1;
+ }
+
+ parse_event_file(pevent, buf, size, sys);
free(buf);
+ return 0;
}
-static void read_ftrace_files(void)
+static int read_ftrace_files(struct pevent *pevent)
{
unsigned long long size;
int count;
int i;
+ int ret;
- count = read4();
+ count = read4(pevent);
for (i = 0; i < count; i++) {
- size = read8();
- read_ftrace_file(size);
+ size = read8(pevent);
+ ret = read_ftrace_file(pevent, size);
+ if (ret)
+ return ret;
}
+ return 0;
}
-static void read_event_files(void)
+static int read_event_files(struct pevent *pevent)
{
unsigned long long size;
char *sys;
int systems;
int count;
int i,x;
+ int ret;
- systems = read4();
+ systems = read4(pevent);
for (i = 0; i < systems; i++) {
sys = read_string();
+ if (sys == NULL)
+ return -1;
- count = read4();
- for (x=0; x < count; x++) {
- size = read8();
- read_event_file(sys, size);
- }
- }
-}
-
-struct cpu_data {
- unsigned long long offset;
- unsigned long long size;
- unsigned long long timestamp;
- struct record *next;
- char *page;
- int cpu;
- int index;
- int page_size;
-};
-
-static struct cpu_data *cpu_data;
-
-static void update_cpu_data_index(int cpu)
-{
- cpu_data[cpu].offset += page_size;
- cpu_data[cpu].size -= page_size;
- cpu_data[cpu].index = 0;
-}
-
-static void get_next_page(int cpu)
-{
- off_t save_seek;
- off_t ret;
-
- if (!cpu_data[cpu].page)
- return;
-
- if (read_page) {
- if (cpu_data[cpu].size <= page_size) {
- free(cpu_data[cpu].page);
- cpu_data[cpu].page = NULL;
- return;
- }
-
- update_cpu_data_index(cpu);
-
- /* other parts of the code may expect the pointer to not move */
- save_seek = lseek(input_fd, 0, SEEK_CUR);
-
- ret = lseek(input_fd, cpu_data[cpu].offset, SEEK_SET);
- if (ret == (off_t)-1)
- die("failed to lseek");
- ret = read(input_fd, cpu_data[cpu].page, page_size);
- if (ret < 0)
- die("failed to read page");
-
- /* reset the file pointer back */
- lseek(input_fd, save_seek, SEEK_SET);
-
- return;
- }
-
- munmap(cpu_data[cpu].page, page_size);
- cpu_data[cpu].page = NULL;
-
- if (cpu_data[cpu].size <= page_size)
- return;
-
- update_cpu_data_index(cpu);
-
- cpu_data[cpu].page = mmap(NULL, page_size, PROT_READ, MAP_PRIVATE,
- input_fd, cpu_data[cpu].offset);
- if (cpu_data[cpu].page == MAP_FAILED)
- die("failed to mmap cpu %d at offset 0x%llx",
- cpu, cpu_data[cpu].offset);
-}
-
-static unsigned int type_len4host(unsigned int type_len_ts)
-{
- if (file_bigendian)
- return (type_len_ts >> 27) & ((1 << 5) - 1);
- else
- return type_len_ts & ((1 << 5) - 1);
-}
-
-static unsigned int ts4host(unsigned int type_len_ts)
-{
- if (file_bigendian)
- return type_len_ts & ((1 << 27) - 1);
- else
- return type_len_ts >> 5;
-}
-
-static int calc_index(void *ptr, int cpu)
-{
- return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page;
-}
+ count = read4(pevent);
-struct record *trace_peek_data(int cpu)
-{
- struct record *data;
- void *page = cpu_data[cpu].page;
- int idx = cpu_data[cpu].index;
- void *ptr = page + idx;
- unsigned long long extend;
- unsigned int type_len_ts;
- unsigned int type_len;
- unsigned int delta;
- unsigned int length = 0;
-
- if (cpu_data[cpu].next)
- return cpu_data[cpu].next;
-
- if (!page)
- return NULL;
-
- if (!idx) {
- /* FIXME: handle header page */
- if (header_page_ts_size != 8)
- die("expected a long long type for timestamp");
- cpu_data[cpu].timestamp = data2host8(ptr);
- ptr += 8;
- switch (header_page_size_size) {
- case 4:
- cpu_data[cpu].page_size = data2host4(ptr);
- ptr += 4;
- break;
- case 8:
- cpu_data[cpu].page_size = data2host8(ptr);
- ptr += 8;
- break;
- default:
- die("bad long size");
+ for (x=0; x < count; x++) {
+ size = read8(pevent);
+ ret = read_event_file(pevent, sys, size);
+ if (ret)
+ return ret;
}
- ptr = cpu_data[cpu].page + header_page_data_offset;
}
-
-read_again:
- idx = calc_index(ptr, cpu);
-
- if (idx >= cpu_data[cpu].page_size) {
- get_next_page(cpu);
- return trace_peek_data(cpu);
- }
-
- type_len_ts = data2host4(ptr);
- ptr += 4;
-
- type_len = type_len4host(type_len_ts);
- delta = ts4host(type_len_ts);
-
- switch (type_len) {
- case RINGBUF_TYPE_PADDING:
- if (!delta)
- die("error, hit unexpected end of page");
- length = data2host4(ptr);
- ptr += 4;
- length *= 4;
- ptr += length;
- goto read_again;
-
- case RINGBUF_TYPE_TIME_EXTEND:
- extend = data2host4(ptr);
- ptr += 4;
- extend <<= TS_SHIFT;
- extend += delta;
- cpu_data[cpu].timestamp += extend;
- goto read_again;
-
- case RINGBUF_TYPE_TIME_STAMP:
- ptr += 12;
- break;
- case 0:
- length = data2host4(ptr);
- ptr += 4;
- die("here! length=%d", length);
- break;
- default:
- length = type_len * 4;
- break;
- }
-
- cpu_data[cpu].timestamp += delta;
-
- data = malloc_or_die(sizeof(*data));
- memset(data, 0, sizeof(*data));
-
- data->ts = cpu_data[cpu].timestamp;
- data->size = length;
- data->data = ptr;
- ptr += length;
-
- cpu_data[cpu].index = calc_index(ptr, cpu);
- cpu_data[cpu].next = data;
-
- return data;
-}
-
-struct record *trace_read_data(int cpu)
-{
- struct record *data;
-
- data = trace_peek_data(cpu);
- cpu_data[cpu].next = NULL;
-
- return data;
+ return 0;
}
-ssize_t trace_report(int fd, bool __repipe)
+ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
{
char buf[BUFSIZ];
char test[] = { 23, 8, 68 };
@@ -486,54 +351,94 @@ ssize_t trace_report(int fd, bool __repipe)
int show_version = 0;
int show_funcs = 0;
int show_printk = 0;
- ssize_t size;
+ ssize_t size = -1;
+ int file_bigendian;
+ int host_bigendian;
+ int file_long_size;
+ int file_page_size;
+ struct pevent *pevent = NULL;
+ int err;
- calc_data_size = 1;
repipe = __repipe;
-
input_fd = fd;
- read_or_die(buf, 3);
- if (memcmp(buf, test, 3) != 0)
- die("no trace data in the file");
+ if (do_read(buf, 3) < 0)
+ return -1;
+ if (memcmp(buf, test, 3) != 0) {
+ pr_debug("no trace data in the file");
+ return -1;
+ }
- read_or_die(buf, 7);
- if (memcmp(buf, "tracing", 7) != 0)
- die("not a trace file (missing 'tracing' tag)");
+ if (do_read(buf, 7) < 0)
+ return -1;
+ if (memcmp(buf, "tracing", 7) != 0) {
+ pr_debug("not a trace file (missing 'tracing' tag)");
+ return -1;
+ }
version = read_string();
+ if (version == NULL)
+ return -1;
if (show_version)
printf("version = %s\n", version);
free(version);
- read_or_die(buf, 1);
+ if (do_read(buf, 1) < 0)
+ return -1;
file_bigendian = buf[0];
host_bigendian = bigendian();
- read_or_die(buf, 1);
- long_size = buf[0];
-
- page_size = read4();
-
- read_header_files();
-
- read_ftrace_files();
- read_event_files();
- read_proc_kallsyms();
- read_ftrace_printk();
+ if (trace_event__init(tevent)) {
+ pr_debug("trace_event__init failed");
+ goto out;
+ }
- size = calc_data_size - 1;
- calc_data_size = 0;
+ pevent = tevent->pevent;
+
+ pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
+ pevent_set_file_bigendian(pevent, file_bigendian);
+ pevent_set_host_bigendian(pevent, host_bigendian);
+
+ if (do_read(buf, 1) < 0)
+ goto out;
+ file_long_size = buf[0];
+
+ file_page_size = read4(pevent);
+ if (!file_page_size)
+ goto out;
+
+ pevent_set_long_size(pevent, file_long_size);
+ pevent_set_page_size(pevent, file_page_size);
+
+ err = read_header_files(pevent);
+ if (err)
+ goto out;
+ err = read_ftrace_files(pevent);
+ if (err)
+ goto out;
+ err = read_event_files(pevent);
+ if (err)
+ goto out;
+ err = read_proc_kallsyms(pevent);
+ if (err)
+ goto out;
+ err = read_ftrace_printk(pevent);
+ if (err)
+ goto out;
+
+ size = trace_data_size;
repipe = false;
if (show_funcs) {
- print_funcs();
- return size;
- }
- if (show_printk) {
- print_printk();
- return size;
+ pevent_print_funcs(pevent);
+ } else if (show_printk) {
+ pevent_print_printk(pevent);
}
+ pevent = NULL;
+
+out:
+ if (pevent)
+ trace_event__cleanup(tevent);
return size;
}