diff options
Diffstat (limited to 'tools/perf')
| -rw-r--r-- | tools/perf/util/header.c | 75 |
1 files changed, 70 insertions, 5 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index d5359e3384e3..5e6d4d29a7a3 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
| @@ -62,6 +62,7 @@ struct perf_file_attr { | |||
| 62 | struct feat_fd { | 62 | struct feat_fd { |
| 63 | struct perf_header *ph; | 63 | struct perf_header *ph; |
| 64 | int fd; | 64 | int fd; |
| 65 | void *buf; /* Either buf != NULL or fd >= 0 */ | ||
| 65 | ssize_t offset; | 66 | ssize_t offset; |
| 66 | size_t size; | 67 | size_t size; |
| 67 | }; | 68 | }; |
| @@ -81,19 +82,52 @@ bool perf_header__has_feat(const struct perf_header *header, int feat) | |||
| 81 | return test_bit(feat, header->adds_features); | 82 | return test_bit(feat, header->adds_features); |
| 82 | } | 83 | } |
| 83 | 84 | ||
| 84 | /* Return: 0 if succeded, -ERR if failed. */ | 85 | static int __do_write_fd(struct feat_fd *ff, const void *buf, size_t size) |
| 85 | int do_write(struct feat_fd *ff, const void *buf, size_t size) | ||
| 86 | { | 86 | { |
| 87 | ssize_t ret; | 87 | ssize_t ret = writen(ff->fd, buf, size); |
| 88 | 88 | ||
| 89 | ret = writen(ff->fd, buf, size); | ||
| 90 | if (ret != (ssize_t)size) | 89 | if (ret != (ssize_t)size) |
| 91 | return ret < 0 ? (int)ret : -1; | 90 | return ret < 0 ? (int)ret : -1; |
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static int __do_write_buf(struct feat_fd *ff, const void *buf, size_t size) | ||
| 95 | { | ||
| 96 | /* struct perf_event_header::size is u16 */ | ||
| 97 | const size_t max_size = 0xffff - sizeof(struct perf_event_header); | ||
| 98 | size_t new_size = ff->size; | ||
| 99 | void *addr; | ||
| 100 | |||
| 101 | if (size + ff->offset > max_size) | ||
| 102 | return -E2BIG; | ||
| 103 | |||
| 104 | while (size > (new_size - ff->offset)) | ||
| 105 | new_size <<= 1; | ||
| 106 | new_size = min(max_size, new_size); | ||
| 107 | |||
| 108 | if (ff->size < new_size) { | ||
| 109 | addr = realloc(ff->buf, new_size); | ||
| 110 | if (!addr) | ||
| 111 | return -ENOMEM; | ||
| 112 | ff->buf = addr; | ||
| 113 | ff->size = new_size; | ||
| 114 | } | ||
| 115 | |||
| 116 | memcpy(ff->buf + ff->offset, buf, size); | ||
| 117 | ff->offset += size; | ||
| 92 | 118 | ||
| 93 | return 0; | 119 | return 0; |
| 94 | } | 120 | } |
| 95 | 121 | ||
| 96 | /* Return: 0 if succeded, -ERR if failed. */ | 122 | /* Return: 0 if succeded, -ERR if failed. */ |
| 123 | int do_write(struct feat_fd *ff, const void *buf, size_t size) | ||
| 124 | { | ||
| 125 | if (!ff->buf) | ||
| 126 | return __do_write_fd(ff, buf, size); | ||
| 127 | return __do_write_buf(ff, buf, size); | ||
| 128 | } | ||
| 129 | |||
| 130 | /* Return: 0 if succeded, -ERR if failed. */ | ||
| 97 | int write_padded(struct feat_fd *ff, const void *bf, | 131 | int write_padded(struct feat_fd *ff, const void *bf, |
| 98 | size_t count, size_t count_aligned) | 132 | size_t count, size_t count_aligned) |
| 99 | { | 133 | { |
| @@ -126,7 +160,7 @@ static int do_write_string(struct feat_fd *ff, const char *str) | |||
| 126 | return write_padded(ff, str, olen, len); | 160 | return write_padded(ff, str, olen, len); |
| 127 | } | 161 | } |
| 128 | 162 | ||
| 129 | static int __do_read(struct feat_fd *ff, void *addr, ssize_t size) | 163 | static int __do_read_fd(struct feat_fd *ff, void *addr, ssize_t size) |
| 130 | { | 164 | { |
| 131 | ssize_t ret = readn(ff->fd, addr, size); | 165 | ssize_t ret = readn(ff->fd, addr, size); |
| 132 | 166 | ||
| @@ -135,6 +169,25 @@ static int __do_read(struct feat_fd *ff, void *addr, ssize_t size) | |||
| 135 | return 0; | 169 | return 0; |
| 136 | } | 170 | } |
| 137 | 171 | ||
| 172 | static int __do_read_buf(struct feat_fd *ff, void *addr, ssize_t size) | ||
| 173 | { | ||
| 174 | if (size > (ssize_t)ff->size - ff->offset) | ||
| 175 | return -1; | ||
| 176 | |||
| 177 | memcpy(addr, ff->buf + ff->offset, size); | ||
| 178 | ff->offset += size; | ||
| 179 | |||
| 180 | return 0; | ||
| 181 | |||
| 182 | } | ||
| 183 | |||
| 184 | static int __do_read(struct feat_fd *ff, void *addr, ssize_t size) | ||
| 185 | { | ||
| 186 | if (!ff->buf) | ||
| 187 | return __do_read_fd(ff, addr, size); | ||
| 188 | return __do_read_buf(ff, addr, size); | ||
| 189 | } | ||
| 190 | |||
| 138 | static int do_read_u32(struct feat_fd *ff, u32 *addr) | 191 | static int do_read_u32(struct feat_fd *ff, u32 *addr) |
| 139 | { | 192 | { |
| 140 | int ret; | 193 | int ret; |
| @@ -189,6 +242,9 @@ static char *do_read_string(struct feat_fd *ff) | |||
| 189 | static int write_tracing_data(struct feat_fd *ff, | 242 | static int write_tracing_data(struct feat_fd *ff, |
| 190 | struct perf_evlist *evlist) | 243 | struct perf_evlist *evlist) |
| 191 | { | 244 | { |
| 245 | if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__)) | ||
| 246 | return -1; | ||
| 247 | |||
| 192 | return read_tracing_data(ff->fd, &evlist->entries); | 248 | return read_tracing_data(ff->fd, &evlist->entries); |
| 193 | } | 249 | } |
| 194 | 250 | ||
| @@ -203,6 +259,9 @@ static int write_build_id(struct feat_fd *ff, | |||
| 203 | if (!perf_session__read_build_ids(session, true)) | 259 | if (!perf_session__read_build_ids(session, true)) |
| 204 | return -1; | 260 | return -1; |
| 205 | 261 | ||
| 262 | if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__)) | ||
| 263 | return -1; | ||
| 264 | |||
| 206 | err = perf_session__write_buildid_table(session, ff); | 265 | err = perf_session__write_buildid_table(session, ff); |
| 207 | if (err < 0) { | 266 | if (err < 0) { |
| 208 | pr_debug("failed to write buildid table\n"); | 267 | pr_debug("failed to write buildid table\n"); |
| @@ -912,6 +971,9 @@ static int write_auxtrace(struct feat_fd *ff, | |||
| 912 | struct perf_session *session; | 971 | struct perf_session *session; |
| 913 | int err; | 972 | int err; |
| 914 | 973 | ||
| 974 | if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__)) | ||
| 975 | return -1; | ||
| 976 | |||
| 915 | session = container_of(ff->ph, struct perf_session, header); | 977 | session = container_of(ff->ph, struct perf_session, header); |
| 916 | 978 | ||
| 917 | err = auxtrace_index__write(ff->fd, &session->auxtrace_index); | 979 | err = auxtrace_index__write(ff->fd, &session->auxtrace_index); |
| @@ -2197,6 +2259,9 @@ static int do_write_feat(struct feat_fd *ff, int type, | |||
| 2197 | if (!feat_ops[type].write) | 2259 | if (!feat_ops[type].write) |
| 2198 | return -1; | 2260 | return -1; |
| 2199 | 2261 | ||
| 2262 | if (WARN(ff->buf, "Error: calling %s in pipe-mode.\n", __func__)) | ||
| 2263 | return -1; | ||
| 2264 | |||
| 2200 | (*p)->offset = lseek(ff->fd, 0, SEEK_CUR); | 2265 | (*p)->offset = lseek(ff->fd, 0, SEEK_CUR); |
| 2201 | 2266 | ||
| 2202 | err = feat_ops[type].write(ff, evlist); | 2267 | err = feat_ops[type].write(ff, evlist); |
