diff options
-rw-r--r-- | tools/perf/util/header.c | 53 | ||||
-rw-r--r-- | tools/perf/util/session.c | 4 |
2 files changed, 50 insertions, 7 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 9f867d96c6a5..666f18972fa3 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -1973,6 +1973,51 @@ static int perf_header__read_pipe(struct perf_session *session, int fd) | |||
1973 | return 0; | 1973 | return 0; |
1974 | } | 1974 | } |
1975 | 1975 | ||
1976 | static int read_attr(int fd, struct perf_header *ph, | ||
1977 | struct perf_file_attr *f_attr) | ||
1978 | { | ||
1979 | struct perf_event_attr *attr = &f_attr->attr; | ||
1980 | size_t sz, left; | ||
1981 | size_t our_sz = sizeof(f_attr->attr); | ||
1982 | int ret; | ||
1983 | |||
1984 | memset(f_attr, 0, sizeof(*f_attr)); | ||
1985 | |||
1986 | /* read minimal guaranteed structure */ | ||
1987 | ret = readn(fd, attr, PERF_ATTR_SIZE_VER0); | ||
1988 | if (ret <= 0) { | ||
1989 | pr_debug("cannot read %d bytes of header attr\n", | ||
1990 | PERF_ATTR_SIZE_VER0); | ||
1991 | return -1; | ||
1992 | } | ||
1993 | |||
1994 | /* on file perf_event_attr size */ | ||
1995 | sz = attr->size; | ||
1996 | if (ph->needs_swap) | ||
1997 | sz = bswap_32(sz); | ||
1998 | |||
1999 | if (sz == 0) { | ||
2000 | /* assume ABI0 */ | ||
2001 | sz = PERF_ATTR_SIZE_VER0; | ||
2002 | } else if (sz > our_sz) { | ||
2003 | pr_debug("file uses a more recent and unsupported ABI" | ||
2004 | " (%zu bytes extra)\n", sz - our_sz); | ||
2005 | return -1; | ||
2006 | } | ||
2007 | /* what we have not yet read and that we know about */ | ||
2008 | left = sz - PERF_ATTR_SIZE_VER0; | ||
2009 | if (left) { | ||
2010 | void *ptr = attr; | ||
2011 | ptr += PERF_ATTR_SIZE_VER0; | ||
2012 | |||
2013 | ret = readn(fd, ptr, left); | ||
2014 | } | ||
2015 | /* read perf_file_section, ids are read in caller */ | ||
2016 | ret = readn(fd, &f_attr->ids, sizeof(f_attr->ids)); | ||
2017 | |||
2018 | return ret <= 0 ? -1 : 0; | ||
2019 | } | ||
2020 | |||
1976 | int perf_session__read_header(struct perf_session *session, int fd) | 2021 | int perf_session__read_header(struct perf_session *session, int fd) |
1977 | { | 2022 | { |
1978 | struct perf_header *header = &session->header; | 2023 | struct perf_header *header = &session->header; |
@@ -1988,19 +2033,17 @@ int perf_session__read_header(struct perf_session *session, int fd) | |||
1988 | if (session->fd_pipe) | 2033 | if (session->fd_pipe) |
1989 | return perf_header__read_pipe(session, fd); | 2034 | return perf_header__read_pipe(session, fd); |
1990 | 2035 | ||
1991 | if (perf_file_header__read(&f_header, header, fd) < 0) { | 2036 | if (perf_file_header__read(&f_header, header, fd) < 0) |
1992 | pr_debug("incompatible file format\n"); | ||
1993 | return -EINVAL; | 2037 | return -EINVAL; |
1994 | } | ||
1995 | 2038 | ||
1996 | nr_attrs = f_header.attrs.size / sizeof(f_attr); | 2039 | nr_attrs = f_header.attrs.size / f_header.attr_size; |
1997 | lseek(fd, f_header.attrs.offset, SEEK_SET); | 2040 | lseek(fd, f_header.attrs.offset, SEEK_SET); |
1998 | 2041 | ||
1999 | for (i = 0; i < nr_attrs; i++) { | 2042 | for (i = 0; i < nr_attrs; i++) { |
2000 | struct perf_evsel *evsel; | 2043 | struct perf_evsel *evsel; |
2001 | off_t tmp; | 2044 | off_t tmp; |
2002 | 2045 | ||
2003 | if (readn(fd, &f_attr, sizeof(f_attr)) <= 0) | 2046 | if (read_attr(fd, header, &f_attr) < 0) |
2004 | goto out_errno; | 2047 | goto out_errno; |
2005 | 2048 | ||
2006 | if (header->needs_swap) | 2049 | if (header->needs_swap) |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index bec8a328b1b8..e650de8f4396 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -24,7 +24,7 @@ static int perf_session__open(struct perf_session *self, bool force) | |||
24 | self->fd = STDIN_FILENO; | 24 | self->fd = STDIN_FILENO; |
25 | 25 | ||
26 | if (perf_session__read_header(self, self->fd) < 0) | 26 | if (perf_session__read_header(self, self->fd) < 0) |
27 | pr_err("incompatible file format"); | 27 | pr_err("incompatible file format (rerun with -v to learn more)"); |
28 | 28 | ||
29 | return 0; | 29 | return 0; |
30 | } | 30 | } |
@@ -56,7 +56,7 @@ static int perf_session__open(struct perf_session *self, bool force) | |||
56 | } | 56 | } |
57 | 57 | ||
58 | if (perf_session__read_header(self, self->fd) < 0) { | 58 | if (perf_session__read_header(self, self->fd) < 0) { |
59 | pr_err("incompatible file format"); | 59 | pr_err("incompatible file format (rerun with -v to learn more)"); |
60 | goto out_close; | 60 | goto out_close; |
61 | } | 61 | } |
62 | 62 | ||