diff options
Diffstat (limited to 'tools/perf/util/trace-event-read.c')
-rw-r--r-- | tools/perf/util/trace-event-read.c | 473 |
1 files changed, 177 insertions, 296 deletions
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 3741572696af..af215c0d2379 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> @@ -41,26 +39,14 @@ static int input_fd; -static int read_page; - int file_bigendian; int host_bigendian; static int long_size; -static ssize_t calc_data_size; +static ssize_t trace_data_size; static bool repipe; -static void *malloc_or_die(int size) -{ - void *ret; - - ret = malloc(size); - if (!ret) - die("malloc"); - return ret; -} - -static int do_read(int fd, void *buf, int size) +static int __do_read(int fd, void *buf, int size) { int rsize = size; @@ -73,8 +59,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; @@ -84,17 +72,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; } @@ -107,7 +96,7 @@ static void skip(int size) while (size) { r = size > BUFSIZ ? BUFSIZ : size; - read_or_die(buf, r); + do_read(buf, r); size -= r; }; } @@ -116,7 +105,8 @@ static unsigned int read4(struct pevent *pevent) { unsigned int data; - read_or_die(&data, 4); + if (do_read(&data, 4) < 0) + return 0; return __data2host4(pevent, data); } @@ -124,7 +114,8 @@ static unsigned long long read8(struct pevent *pevent) { unsigned long long data; - read_or_die(&data, 8); + if (do_read(&data, 8) < 0) + return 0; return __data2host8(pevent, data); } @@ -138,17 +129,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; @@ -157,60 +154,79 @@ 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(struct pevent *pevent) +static int read_proc_kallsyms(struct pevent *pevent) { unsigned int size; char *buf; 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(pevent, buf, size); free(buf); + return 0; } -static void read_ftrace_printk(struct pevent *pevent) +static int read_ftrace_printk(struct pevent *pevent) { unsigned int size; char *buf; + /* 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(pevent, buf, size); free(buf); + return 0; } -static void read_header_files(struct pevent *pevent) +static int read_header_files(struct pevent *pevent) { unsigned long long size; char *header_event; 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(pevent); skip(size); @@ -221,269 +237,107 @@ static void read_header_files(struct pevent *pevent) */ long_size = header_page_size_size; - 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; + + if (memcmp(buf, "header_event", 13) != 0) { + pr_debug("did not read header event"); + return -1; + } size = read8(pevent); - header_event = malloc_or_die(size); - read_or_die(header_event, size); + header_event = malloc(size); + if (header_event == NULL) + return -1; + + if (do_read(header_event, size) < 0) + ret = -1; + free(header_event); + return ret; } -static void read_ftrace_file(struct pevent *pevent, 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); + 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(struct pevent *pevent, char *sys, +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); + 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(struct pevent *pevent) +static int read_ftrace_files(struct pevent *pevent) { unsigned long long size; int count; int i; + int ret; count = read4(pevent); for (i = 0; i < count; i++) { size = read8(pevent); - read_ftrace_file(pevent, size); + ret = read_ftrace_file(pevent, size); + if (ret) + return ret; } + return 0; } -static void read_event_files(struct pevent *pevent) +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(pevent); for (i = 0; i < systems; i++) { sys = read_string(); + if (sys == NULL) + return -1; count = read4(pevent); + for (x=0; x < count; x++) { size = read8(pevent); - read_event_file(pevent, sys, size); + ret = read_event_file(pevent, sys, size); + if (ret) + return ret; } } -} - -struct cpu_data { - unsigned long long offset; - unsigned long long size; - unsigned long long timestamp; - struct pevent_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; -} - -struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu) -{ - struct pevent_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(pevent, ptr); - ptr += 8; - switch (header_page_size_size) { - case 4: - cpu_data[cpu].page_size = data2host4(pevent, ptr); - ptr += 4; - break; - case 8: - cpu_data[cpu].page_size = data2host8(pevent, ptr); - ptr += 8; - break; - default: - die("bad long size"); - } - 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(pevent, cpu); - } - - type_len_ts = data2host4(pevent, 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(pevent, ptr); - ptr += 4; - length *= 4; - ptr += length; - goto read_again; - - case RINGBUF_TYPE_TIME_EXTEND: - extend = data2host4(pevent, 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(pevent, 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 pevent_record *trace_read_data(struct pevent *pevent, int cpu) -{ - struct pevent_record *data; - - data = trace_peek_data(pevent, cpu); - cpu_data[cpu].next = NULL; - - return data; + return 0; } ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) @@ -494,58 +348,85 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) int show_version = 0; int show_funcs = 0; int show_printk = 0; - ssize_t size; + ssize_t size = -1; + struct pevent *pevent; + int err; - calc_data_size = 1; - repipe = __repipe; + *ppevent = NULL; + 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(); - *ppevent = read_trace_init(file_bigendian, host_bigendian); - if (*ppevent == NULL) - die("read_trace_init failed"); + pevent = read_trace_init(file_bigendian, host_bigendian); + if (pevent == NULL) { + pr_debug("read_trace_init failed"); + goto out; + } - read_or_die(buf, 1); + if (do_read(buf, 1) < 0) + goto out; long_size = buf[0]; - page_size = read4(*ppevent); - - read_header_files(*ppevent); - - read_ftrace_files(*ppevent); - read_event_files(*ppevent); - read_proc_kallsyms(*ppevent); - read_ftrace_printk(*ppevent); - - size = calc_data_size - 1; - calc_data_size = 0; + page_size = read4(pevent); + if (!page_size) + goto out; + + 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) { - pevent_print_funcs(*ppevent); - return size; - } - if (show_printk) { - pevent_print_printk(*ppevent); - return size; + pevent_print_funcs(pevent); + } else if (show_printk) { + pevent_print_printk(pevent); } + *ppevent = pevent; + pevent = NULL; + +out: + if (pevent) + pevent_free(pevent); return size; } |