diff options
Diffstat (limited to 'tools/perf/util/trace-event-read.c')
| -rw-r--r-- | tools/perf/util/trace-event-read.c | 246 |
1 files changed, 147 insertions, 99 deletions
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index af215c0d2379..ecbbb93f0185 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -1,48 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com> - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License (not later!) - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #include <dirent.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <getopt.h> #include <stdarg.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/wait.h> #include <sys/mman.h> -#include <pthread.h> +#include <event-parse.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> -#include "../perf.h" -#include "util.h" #include "trace-event.h" +#include "debug.h" +#include "util.h" static int input_fd; -int file_bigendian; -int host_bigendian; -static int long_size; - static ssize_t trace_data_size; static bool repipe; @@ -98,25 +77,25 @@ static void skip(int size) r = size > BUFSIZ ? BUFSIZ : size; do_read(buf, r); size -= r; - }; + } } -static unsigned int read4(struct pevent *pevent) +static unsigned int read4(struct tep_handle *pevent) { unsigned int data; if (do_read(&data, 4) < 0) return 0; - return __data2host4(pevent, data); + return tep_read_number(pevent, &data, 4); } -static unsigned long long read8(struct pevent *pevent) +static unsigned long long read8(struct tep_handle *pevent) { unsigned long long data; if (do_read(&data, 8) < 0) return 0; - return __data2host8(pevent, data); + return tep_read_number(pevent, &data, 8); } static char *read_string(void) @@ -163,32 +142,30 @@ out: return str; } -static int read_proc_kallsyms(struct pevent *pevent) +static int read_proc_kallsyms(struct tep_handle *pevent) { unsigned int size; - char *buf; size = read4(pevent); if (!size) return 0; - - buf = malloc(size + 1); - if (buf == NULL) - return -1; - - if (do_read(buf, size) < 0) { - free(buf); - return -1; - } - buf[size] = '\0'; - - parse_proc_kallsyms(pevent, buf, size); - - free(buf); + /* + * Just skip it, now that we configure libtraceevent to use the + * tools/perf/ symbol resolver. + * + * We need to skip it so that we can continue parsing old perf.data + * files, that contains this /proc/kallsyms payload. + * + * Newer perf.data files will have just the 4-bytes zeros "kallsyms + * payload", so that older tools can continue reading it and interpret + * it as "no kallsyms payload is present". + */ + lseek(input_fd, size, SEEK_CUR); + trace_data_size += size; return 0; } -static int read_ftrace_printk(struct pevent *pevent) +static int read_ftrace_printk(struct tep_handle *pevent) { unsigned int size; char *buf; @@ -198,7 +175,7 @@ static int read_ftrace_printk(struct pevent *pevent) if (!size) return 0; - buf = malloc(size); + buf = malloc(size + 1); if (buf == NULL) return -1; @@ -207,16 +184,18 @@ static int read_ftrace_printk(struct pevent *pevent) return -1; } + buf[size] = '\0'; + parse_ftrace_printk(pevent, buf, size); free(buf); return 0; } -static int read_header_files(struct pevent *pevent) +static int read_header_files(struct tep_handle *pevent) { unsigned long long size; - char *header_event; + char *header_page; char buf[BUFSIZ]; int ret = 0; @@ -229,13 +208,26 @@ static int read_header_files(struct pevent *pevent) } size = read8(pevent); - skip(size); - /* - * The size field in the page is of type long, - * use that instead, since it represents the kernel. - */ - long_size = header_page_size_size; + header_page = malloc(size); + if (header_page == NULL) + return -1; + + if (do_read(header_page, size) < 0) { + pr_debug("did not read header page"); + free(header_page); + return -1; + } + + if (!tep_parse_header_page(pevent, header_page, size, + tep_get_long_size(pevent))) { + /* + * The commit field in the page is of type long, + * use that instead, since it represents the kernel. + */ + tep_set_long_size(pevent, tep_get_header_page_size(pevent)); + } + free(header_page); if (do_read(buf, 13) < 0) return -1; @@ -246,55 +238,61 @@ static int read_header_files(struct pevent *pevent) } size = read8(pevent); - header_event = malloc(size); - if (header_event == NULL) - return -1; - - if (do_read(header_event, size) < 0) - ret = -1; + skip(size); - free(header_event); return ret; } -static int read_ftrace_file(struct pevent *pevent, unsigned long long size) +static int read_ftrace_file(struct tep_handle *pevent, unsigned long long size) { + int ret; char *buf; buf = malloc(size); - if (buf == NULL) + if (buf == NULL) { + pr_debug("memory allocation failure\n"); return -1; + } - if (do_read(buf, size) < 0) { - free(buf); - return -1; + ret = do_read(buf, size); + if (ret < 0) { + pr_debug("error reading ftrace file.\n"); + goto out; } - parse_ftrace_file(pevent, buf, size); + ret = parse_ftrace_file(pevent, buf, size); + if (ret < 0) + pr_debug("error parsing ftrace file.\n"); +out: free(buf); - return 0; + return ret; } -static int read_event_file(struct pevent *pevent, char *sys, - unsigned long long size) +static int read_event_file(struct tep_handle *pevent, char *sys, + unsigned long long size) { + int ret; char *buf; buf = malloc(size); - if (buf == NULL) - return -1; - - if (do_read(buf, size) < 0) { - free(buf); + if (buf == NULL) { + pr_debug("memory allocation failure\n"); return -1; } - parse_event_file(pevent, buf, size, sys); + ret = do_read(buf, size); + if (ret < 0) + goto out; + + ret = parse_event_file(pevent, buf, size, sys); + if (ret < 0) + pr_debug("error parsing event file.\n"); +out: free(buf); - return 0; + return ret; } -static int read_ftrace_files(struct pevent *pevent) +static int read_ftrace_files(struct tep_handle *pevent) { unsigned long long size; int count; @@ -312,7 +310,7 @@ static int read_ftrace_files(struct pevent *pevent) return 0; } -static int read_event_files(struct pevent *pevent) +static int read_event_files(struct tep_handle *pevent) { unsigned long long size; char *sys; @@ -333,14 +331,48 @@ static int read_event_files(struct pevent *pevent) for (x=0; x < count; x++) { size = read8(pevent); ret = read_event_file(pevent, sys, size); - if (ret) + if (ret) { + free(sys); return ret; + } } + free(sys); } return 0; } -ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) +static int read_saved_cmdline(struct tep_handle *pevent) +{ + unsigned long long size; + char *buf; + int ret; + + /* it can have 0 size */ + size = read8(pevent); + if (!size) + return 0; + + buf = malloc(size + 1); + if (buf == NULL) { + pr_debug("memory allocation failure\n"); + return -1; + } + + ret = do_read(buf, size); + if (ret < 0) { + pr_debug("error reading saved cmdlines\n"); + goto out; + } + buf[ret] = '\0'; + + parse_saved_cmdline(pevent, buf, size); + ret = 0; +out: + free(buf); + return ret; +} + +ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe) { char buf[BUFSIZ]; char test[] = { 23, 8, 68 }; @@ -349,11 +381,13 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) int show_funcs = 0; int show_printk = 0; ssize_t size = -1; - struct pevent *pevent; + int file_bigendian; + int host_bigendian; + int file_long_size; + int file_page_size; + struct tep_handle *pevent = NULL; int err; - *ppevent = NULL; - repipe = __repipe; input_fd = fd; @@ -376,27 +410,36 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) return -1; if (show_version) printf("version = %s\n", version); - free(version); - if (do_read(buf, 1) < 0) + if (do_read(buf, 1) < 0) { + free(version); return -1; + } file_bigendian = buf[0]; - host_bigendian = bigendian(); + host_bigendian = host_is_bigendian() ? 1 : 0; - pevent = read_trace_init(file_bigendian, host_bigendian); - if (pevent == NULL) { - pr_debug("read_trace_init failed"); + if (trace_event__init(tevent)) { + pr_debug("trace_event__init failed"); goto out; } + pevent = tevent->pevent; + + tep_set_flag(pevent, TEP_NSEC_OUTPUT); + tep_set_file_bigendian(pevent, file_bigendian); + tep_set_local_bigendian(pevent, host_bigendian); + if (do_read(buf, 1) < 0) goto out; - long_size = buf[0]; + file_long_size = buf[0]; - page_size = read4(pevent); - if (!page_size) + file_page_size = read4(pevent); + if (!file_page_size) goto out; + tep_set_long_size(pevent, file_long_size); + tep_set_page_size(pevent, file_page_size); + err = read_header_files(pevent); if (err) goto out; @@ -412,21 +455,26 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) err = read_ftrace_printk(pevent); if (err) goto out; + if (atof(version) >= 0.6) { + err = read_saved_cmdline(pevent); + if (err) + goto out; + } size = trace_data_size; repipe = false; if (show_funcs) { - pevent_print_funcs(pevent); + tep_print_funcs(pevent); } else if (show_printk) { - pevent_print_printk(pevent); + tep_print_printk(pevent); } - *ppevent = pevent; pevent = NULL; out: if (pevent) - pevent_free(pevent); + trace_event__cleanup(tevent); + free(version); return size; } |
