diff options
Diffstat (limited to 'tools/perf/util/header.c')
| -rw-r--r-- | tools/perf/util/header.c | 403 |
1 files changed, 320 insertions, 83 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index e306857b2c2b..4805e6dfd23c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
| @@ -2,9 +2,15 @@ | |||
| 2 | #include <unistd.h> | 2 | #include <unistd.h> |
| 3 | #include <stdio.h> | 3 | #include <stdio.h> |
| 4 | #include <stdlib.h> | 4 | #include <stdlib.h> |
| 5 | #include <linux/list.h> | ||
| 5 | 6 | ||
| 6 | #include "util.h" | 7 | #include "util.h" |
| 7 | #include "header.h" | 8 | #include "header.h" |
| 9 | #include "../perf.h" | ||
| 10 | #include "trace-event.h" | ||
| 11 | #include "symbol.h" | ||
| 12 | #include "data_map.h" | ||
| 13 | #include "debug.h" | ||
| 8 | 14 | ||
| 9 | /* | 15 | /* |
| 10 | * Create new perf.data header attribute: | 16 | * Create new perf.data header attribute: |
| @@ -13,32 +19,43 @@ struct perf_header_attr *perf_header_attr__new(struct perf_event_attr *attr) | |||
| 13 | { | 19 | { |
| 14 | struct perf_header_attr *self = malloc(sizeof(*self)); | 20 | struct perf_header_attr *self = malloc(sizeof(*self)); |
| 15 | 21 | ||
| 16 | if (!self) | 22 | if (self != NULL) { |
| 17 | die("nomem"); | 23 | self->attr = *attr; |
| 18 | 24 | self->ids = 0; | |
| 19 | self->attr = *attr; | 25 | self->size = 1; |
| 20 | self->ids = 0; | 26 | self->id = malloc(sizeof(u64)); |
| 21 | self->size = 1; | 27 | if (self->id == NULL) { |
| 22 | self->id = malloc(sizeof(u64)); | 28 | free(self); |
| 23 | 29 | self = NULL; | |
| 24 | if (!self->id) | 30 | } |
| 25 | die("nomem"); | 31 | } |
| 26 | 32 | ||
| 27 | return self; | 33 | return self; |
| 28 | } | 34 | } |
| 29 | 35 | ||
| 30 | void perf_header_attr__add_id(struct perf_header_attr *self, u64 id) | 36 | void perf_header_attr__delete(struct perf_header_attr *self) |
| 37 | { | ||
| 38 | free(self->id); | ||
| 39 | free(self); | ||
| 40 | } | ||
| 41 | |||
| 42 | int perf_header_attr__add_id(struct perf_header_attr *self, u64 id) | ||
| 31 | { | 43 | { |
| 32 | int pos = self->ids; | 44 | int pos = self->ids; |
| 33 | 45 | ||
| 34 | self->ids++; | 46 | self->ids++; |
| 35 | if (self->ids > self->size) { | 47 | if (self->ids > self->size) { |
| 36 | self->size *= 2; | 48 | int nsize = self->size * 2; |
| 37 | self->id = realloc(self->id, self->size * sizeof(u64)); | 49 | u64 *nid = realloc(self->id, nsize * sizeof(u64)); |
| 38 | if (!self->id) | 50 | |
| 39 | die("nomem"); | 51 | if (nid == NULL) |
| 52 | return -1; | ||
| 53 | |||
| 54 | self->size = nsize; | ||
| 55 | self->id = nid; | ||
| 40 | } | 56 | } |
| 41 | self->id[pos] = id; | 57 | self->id[pos] = id; |
| 58 | return 0; | ||
| 42 | } | 59 | } |
| 43 | 60 | ||
| 44 | /* | 61 | /* |
| @@ -46,42 +63,52 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id) | |||
| 46 | */ | 63 | */ |
| 47 | struct perf_header *perf_header__new(void) | 64 | struct perf_header *perf_header__new(void) |
| 48 | { | 65 | { |
| 49 | struct perf_header *self = malloc(sizeof(*self)); | 66 | struct perf_header *self = zalloc(sizeof(*self)); |
| 50 | 67 | ||
| 51 | if (!self) | 68 | if (self != NULL) { |
| 52 | die("nomem"); | 69 | self->size = 1; |
| 70 | self->attr = malloc(sizeof(void *)); | ||
| 53 | 71 | ||
| 54 | self->frozen = 0; | 72 | if (self->attr == NULL) { |
| 73 | free(self); | ||
| 74 | self = NULL; | ||
| 75 | } | ||
| 76 | } | ||
| 55 | 77 | ||
| 56 | self->attrs = 0; | 78 | return self; |
| 57 | self->size = 1; | 79 | } |
| 58 | self->attr = malloc(sizeof(void *)); | ||
| 59 | 80 | ||
| 60 | if (!self->attr) | 81 | void perf_header__delete(struct perf_header *self) |
| 61 | die("nomem"); | 82 | { |
| 83 | int i; | ||
| 62 | 84 | ||
| 63 | self->data_offset = 0; | 85 | for (i = 0; i < self->attrs; ++i) |
| 64 | self->data_size = 0; | 86 | perf_header_attr__delete(self->attr[i]); |
| 65 | 87 | ||
| 66 | return self; | 88 | free(self->attr); |
| 89 | free(self); | ||
| 67 | } | 90 | } |
| 68 | 91 | ||
| 69 | void perf_header__add_attr(struct perf_header *self, | 92 | int perf_header__add_attr(struct perf_header *self, |
| 70 | struct perf_header_attr *attr) | 93 | struct perf_header_attr *attr) |
| 71 | { | 94 | { |
| 72 | int pos = self->attrs; | ||
| 73 | |||
| 74 | if (self->frozen) | 95 | if (self->frozen) |
| 75 | die("frozen"); | 96 | return -1; |
| 76 | 97 | ||
| 77 | self->attrs++; | 98 | if (self->attrs == self->size) { |
| 78 | if (self->attrs > self->size) { | 99 | int nsize = self->size * 2; |
| 79 | self->size *= 2; | 100 | struct perf_header_attr **nattr; |
| 80 | self->attr = realloc(self->attr, self->size * sizeof(void *)); | 101 | |
| 81 | if (!self->attr) | 102 | nattr = realloc(self->attr, nsize * sizeof(void *)); |
| 82 | die("nomem"); | 103 | if (nattr == NULL) |
| 104 | return -1; | ||
| 105 | |||
| 106 | self->size = nsize; | ||
| 107 | self->attr = nattr; | ||
| 83 | } | 108 | } |
| 84 | self->attr[pos] = attr; | 109 | |
| 110 | self->attr[self->attrs++] = attr; | ||
| 111 | return 0; | ||
| 85 | } | 112 | } |
| 86 | 113 | ||
| 87 | #define MAX_EVENT_NAME 64 | 114 | #define MAX_EVENT_NAME 64 |
| @@ -97,7 +124,7 @@ static struct perf_trace_event_type *events; | |||
| 97 | void perf_header__push_event(u64 id, const char *name) | 124 | void perf_header__push_event(u64 id, const char *name) |
| 98 | { | 125 | { |
| 99 | if (strlen(name) > MAX_EVENT_NAME) | 126 | if (strlen(name) > MAX_EVENT_NAME) |
| 100 | printf("Event %s will be truncated\n", name); | 127 | pr_warning("Event %s will be truncated\n", name); |
| 101 | 128 | ||
| 102 | if (!events) { | 129 | if (!events) { |
| 103 | events = malloc(sizeof(struct perf_trace_event_type)); | 130 | events = malloc(sizeof(struct perf_trace_event_type)); |
| @@ -128,44 +155,137 @@ static const char *__perf_magic = "PERFFILE"; | |||
| 128 | 155 | ||
| 129 | #define PERF_MAGIC (*(u64 *)__perf_magic) | 156 | #define PERF_MAGIC (*(u64 *)__perf_magic) |
| 130 | 157 | ||
| 131 | struct perf_file_section { | ||
| 132 | u64 offset; | ||
| 133 | u64 size; | ||
| 134 | }; | ||
| 135 | |||
| 136 | struct perf_file_attr { | 158 | struct perf_file_attr { |
| 137 | struct perf_event_attr attr; | 159 | struct perf_event_attr attr; |
| 138 | struct perf_file_section ids; | 160 | struct perf_file_section ids; |
| 139 | }; | 161 | }; |
| 140 | 162 | ||
| 141 | struct perf_file_header { | 163 | void perf_header__set_feat(struct perf_header *self, int feat) |
| 142 | u64 magic; | 164 | { |
| 143 | u64 size; | 165 | set_bit(feat, self->adds_features); |
| 144 | u64 attr_size; | 166 | } |
| 145 | struct perf_file_section attrs; | ||
| 146 | struct perf_file_section data; | ||
| 147 | struct perf_file_section event_types; | ||
| 148 | }; | ||
| 149 | 167 | ||
| 150 | static void do_write(int fd, void *buf, size_t size) | 168 | bool perf_header__has_feat(const struct perf_header *self, int feat) |
| 169 | { | ||
| 170 | return test_bit(feat, self->adds_features); | ||
| 171 | } | ||
| 172 | |||
| 173 | static int do_write(int fd, const void *buf, size_t size) | ||
| 151 | { | 174 | { |
| 152 | while (size) { | 175 | while (size) { |
| 153 | int ret = write(fd, buf, size); | 176 | int ret = write(fd, buf, size); |
| 154 | 177 | ||
| 155 | if (ret < 0) | 178 | if (ret < 0) |
| 156 | die("failed to write"); | 179 | return -errno; |
| 157 | 180 | ||
| 158 | size -= ret; | 181 | size -= ret; |
| 159 | buf += ret; | 182 | buf += ret; |
| 160 | } | 183 | } |
| 184 | |||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | static int __dsos__write_buildid_table(struct list_head *head, int fd) | ||
| 189 | { | ||
| 190 | struct dso *pos; | ||
| 191 | |||
| 192 | list_for_each_entry(pos, head, node) { | ||
| 193 | int err; | ||
| 194 | struct build_id_event b; | ||
| 195 | size_t len; | ||
| 196 | |||
| 197 | if (!pos->has_build_id) | ||
| 198 | continue; | ||
| 199 | len = pos->long_name_len + 1; | ||
| 200 | len = ALIGN(len, 64); | ||
| 201 | memset(&b, 0, sizeof(b)); | ||
| 202 | memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); | ||
| 203 | b.header.size = sizeof(b) + len; | ||
| 204 | err = do_write(fd, &b, sizeof(b)); | ||
| 205 | if (err < 0) | ||
| 206 | return err; | ||
| 207 | err = do_write(fd, pos->long_name, len); | ||
| 208 | if (err < 0) | ||
| 209 | return err; | ||
| 210 | } | ||
| 211 | |||
| 212 | return 0; | ||
| 161 | } | 213 | } |
| 162 | 214 | ||
| 163 | void perf_header__write(struct perf_header *self, int fd) | 215 | static int dsos__write_buildid_table(int fd) |
| 216 | { | ||
| 217 | int err = __dsos__write_buildid_table(&dsos__kernel, fd); | ||
| 218 | if (err == 0) | ||
| 219 | err = __dsos__write_buildid_table(&dsos__user, fd); | ||
| 220 | return err; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int perf_header__adds_write(struct perf_header *self, int fd) | ||
| 224 | { | ||
| 225 | int nr_sections; | ||
| 226 | struct perf_file_section *feat_sec; | ||
| 227 | int sec_size; | ||
| 228 | u64 sec_start; | ||
| 229 | int idx = 0, err; | ||
| 230 | |||
| 231 | if (dsos__read_build_ids()) | ||
| 232 | perf_header__set_feat(self, HEADER_BUILD_ID); | ||
| 233 | |||
| 234 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | ||
| 235 | if (!nr_sections) | ||
| 236 | return 0; | ||
| 237 | |||
| 238 | feat_sec = calloc(sizeof(*feat_sec), nr_sections); | ||
| 239 | if (feat_sec == NULL) | ||
| 240 | return -ENOMEM; | ||
| 241 | |||
| 242 | sec_size = sizeof(*feat_sec) * nr_sections; | ||
| 243 | |||
| 244 | sec_start = self->data_offset + self->data_size; | ||
| 245 | lseek(fd, sec_start + sec_size, SEEK_SET); | ||
| 246 | |||
| 247 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { | ||
| 248 | struct perf_file_section *trace_sec; | ||
| 249 | |||
| 250 | trace_sec = &feat_sec[idx++]; | ||
| 251 | |||
| 252 | /* Write trace info */ | ||
| 253 | trace_sec->offset = lseek(fd, 0, SEEK_CUR); | ||
| 254 | read_tracing_data(fd, attrs, nr_counters); | ||
| 255 | trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; | ||
| 256 | } | ||
| 257 | |||
| 258 | |||
| 259 | if (perf_header__has_feat(self, HEADER_BUILD_ID)) { | ||
| 260 | struct perf_file_section *buildid_sec; | ||
| 261 | |||
| 262 | buildid_sec = &feat_sec[idx++]; | ||
| 263 | |||
| 264 | /* Write build-ids */ | ||
| 265 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); | ||
| 266 | err = dsos__write_buildid_table(fd); | ||
| 267 | if (err < 0) { | ||
| 268 | pr_debug("failed to write buildid table\n"); | ||
| 269 | goto out_free; | ||
| 270 | } | ||
| 271 | buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset; | ||
| 272 | } | ||
| 273 | |||
| 274 | lseek(fd, sec_start, SEEK_SET); | ||
| 275 | err = do_write(fd, feat_sec, sec_size); | ||
| 276 | if (err < 0) | ||
| 277 | pr_debug("failed to write feature section\n"); | ||
| 278 | out_free: | ||
| 279 | free(feat_sec); | ||
| 280 | return err; | ||
| 281 | } | ||
| 282 | |||
| 283 | int perf_header__write(struct perf_header *self, int fd, bool at_exit) | ||
| 164 | { | 284 | { |
| 165 | struct perf_file_header f_header; | 285 | struct perf_file_header f_header; |
| 166 | struct perf_file_attr f_attr; | 286 | struct perf_file_attr f_attr; |
| 167 | struct perf_header_attr *attr; | 287 | struct perf_header_attr *attr; |
| 168 | int i; | 288 | int i, err; |
| 169 | 289 | ||
| 170 | lseek(fd, sizeof(f_header), SEEK_SET); | 290 | lseek(fd, sizeof(f_header), SEEK_SET); |
| 171 | 291 | ||
| @@ -174,7 +294,11 @@ void perf_header__write(struct perf_header *self, int fd) | |||
| 174 | attr = self->attr[i]; | 294 | attr = self->attr[i]; |
| 175 | 295 | ||
| 176 | attr->id_offset = lseek(fd, 0, SEEK_CUR); | 296 | attr->id_offset = lseek(fd, 0, SEEK_CUR); |
| 177 | do_write(fd, attr->id, attr->ids * sizeof(u64)); | 297 | err = do_write(fd, attr->id, attr->ids * sizeof(u64)); |
| 298 | if (err < 0) { | ||
| 299 | pr_debug("failed to write perf header\n"); | ||
| 300 | return err; | ||
| 301 | } | ||
| 178 | } | 302 | } |
| 179 | 303 | ||
| 180 | 304 | ||
| @@ -190,17 +314,31 @@ void perf_header__write(struct perf_header *self, int fd) | |||
| 190 | .size = attr->ids * sizeof(u64), | 314 | .size = attr->ids * sizeof(u64), |
| 191 | } | 315 | } |
| 192 | }; | 316 | }; |
| 193 | do_write(fd, &f_attr, sizeof(f_attr)); | 317 | err = do_write(fd, &f_attr, sizeof(f_attr)); |
| 318 | if (err < 0) { | ||
| 319 | pr_debug("failed to write perf header attribute\n"); | ||
| 320 | return err; | ||
| 321 | } | ||
| 194 | } | 322 | } |
| 195 | 323 | ||
| 196 | self->event_offset = lseek(fd, 0, SEEK_CUR); | 324 | self->event_offset = lseek(fd, 0, SEEK_CUR); |
| 197 | self->event_size = event_count * sizeof(struct perf_trace_event_type); | 325 | self->event_size = event_count * sizeof(struct perf_trace_event_type); |
| 198 | if (events) | 326 | if (events) { |
| 199 | do_write(fd, events, self->event_size); | 327 | err = do_write(fd, events, self->event_size); |
| 200 | 328 | if (err < 0) { | |
| 329 | pr_debug("failed to write perf header events\n"); | ||
| 330 | return err; | ||
| 331 | } | ||
| 332 | } | ||
| 201 | 333 | ||
| 202 | self->data_offset = lseek(fd, 0, SEEK_CUR); | 334 | self->data_offset = lseek(fd, 0, SEEK_CUR); |
| 203 | 335 | ||
| 336 | if (at_exit) { | ||
| 337 | err = perf_header__adds_write(self, fd); | ||
| 338 | if (err < 0) | ||
| 339 | return err; | ||
| 340 | } | ||
| 341 | |||
| 204 | f_header = (struct perf_file_header){ | 342 | f_header = (struct perf_file_header){ |
| 205 | .magic = PERF_MAGIC, | 343 | .magic = PERF_MAGIC, |
| 206 | .size = sizeof(f_header), | 344 | .size = sizeof(f_header), |
| @@ -219,11 +357,18 @@ void perf_header__write(struct perf_header *self, int fd) | |||
| 219 | }, | 357 | }, |
| 220 | }; | 358 | }; |
| 221 | 359 | ||
| 360 | memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features)); | ||
| 361 | |||
| 222 | lseek(fd, 0, SEEK_SET); | 362 | lseek(fd, 0, SEEK_SET); |
| 223 | do_write(fd, &f_header, sizeof(f_header)); | 363 | err = do_write(fd, &f_header, sizeof(f_header)); |
| 364 | if (err < 0) { | ||
| 365 | pr_debug("failed to write perf header\n"); | ||
| 366 | return err; | ||
| 367 | } | ||
| 224 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | 368 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); |
| 225 | 369 | ||
| 226 | self->frozen = 1; | 370 | self->frozen = 1; |
| 371 | return 0; | ||
| 227 | } | 372 | } |
| 228 | 373 | ||
| 229 | static void do_read(int fd, void *buf, size_t size) | 374 | static void do_read(int fd, void *buf, size_t size) |
| @@ -241,22 +386,109 @@ static void do_read(int fd, void *buf, size_t size) | |||
| 241 | } | 386 | } |
| 242 | } | 387 | } |
| 243 | 388 | ||
| 244 | struct perf_header *perf_header__read(int fd) | 389 | int perf_header__process_sections(struct perf_header *self, int fd, |
| 390 | int (*process)(struct perf_file_section *self, | ||
| 391 | int feat, int fd)) | ||
| 392 | { | ||
| 393 | struct perf_file_section *feat_sec; | ||
| 394 | int nr_sections; | ||
| 395 | int sec_size; | ||
| 396 | int idx = 0; | ||
| 397 | int err = 0, feat = 1; | ||
| 398 | |||
| 399 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | ||
| 400 | if (!nr_sections) | ||
| 401 | return 0; | ||
| 402 | |||
| 403 | feat_sec = calloc(sizeof(*feat_sec), nr_sections); | ||
| 404 | if (!feat_sec) | ||
| 405 | return -1; | ||
| 406 | |||
| 407 | sec_size = sizeof(*feat_sec) * nr_sections; | ||
| 408 | |||
| 409 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | ||
| 410 | |||
| 411 | do_read(fd, feat_sec, sec_size); | ||
| 412 | |||
| 413 | while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { | ||
| 414 | if (perf_header__has_feat(self, feat)) { | ||
| 415 | struct perf_file_section *sec = &feat_sec[idx++]; | ||
| 416 | |||
| 417 | err = process(sec, feat, fd); | ||
| 418 | if (err < 0) | ||
| 419 | break; | ||
| 420 | } | ||
| 421 | ++feat; | ||
| 422 | } | ||
| 423 | |||
| 424 | free(feat_sec); | ||
| 425 | return err; | ||
| 426 | }; | ||
| 427 | |||
| 428 | int perf_file_header__read(struct perf_file_header *self, | ||
| 429 | struct perf_header *ph, int fd) | ||
| 430 | { | ||
| 431 | lseek(fd, 0, SEEK_SET); | ||
| 432 | do_read(fd, self, sizeof(*self)); | ||
| 433 | |||
| 434 | if (self->magic != PERF_MAGIC || | ||
| 435 | self->attr_size != sizeof(struct perf_file_attr)) | ||
| 436 | return -1; | ||
| 437 | |||
| 438 | if (self->size != sizeof(*self)) { | ||
| 439 | /* Support the previous format */ | ||
| 440 | if (self->size == offsetof(typeof(*self), adds_features)) | ||
| 441 | bitmap_zero(self->adds_features, HEADER_FEAT_BITS); | ||
| 442 | else | ||
| 443 | return -1; | ||
| 444 | } | ||
| 445 | |||
| 446 | memcpy(&ph->adds_features, &self->adds_features, | ||
| 447 | sizeof(self->adds_features)); | ||
| 448 | |||
| 449 | ph->event_offset = self->event_types.offset; | ||
| 450 | ph->event_size = self->event_types.size; | ||
| 451 | ph->data_offset = self->data.offset; | ||
| 452 | ph->data_size = self->data.size; | ||
| 453 | return 0; | ||
| 454 | } | ||
| 455 | |||
| 456 | static int perf_file_section__process(struct perf_file_section *self, | ||
| 457 | int feat, int fd) | ||
| 458 | { | ||
| 459 | if (lseek(fd, self->offset, SEEK_SET) < 0) { | ||
| 460 | pr_debug("Failed to lseek to %Ld offset for feature %d, " | ||
| 461 | "continuing...\n", self->offset, feat); | ||
| 462 | return 0; | ||
| 463 | } | ||
| 464 | |||
| 465 | switch (feat) { | ||
| 466 | case HEADER_TRACE_INFO: | ||
| 467 | trace_report(fd); | ||
| 468 | break; | ||
| 469 | |||
| 470 | case HEADER_BUILD_ID: | ||
| 471 | if (perf_header__read_build_ids(fd, self->offset, self->size)) | ||
| 472 | pr_debug("Failed to read buildids, continuing...\n"); | ||
| 473 | break; | ||
| 474 | default: | ||
| 475 | pr_debug("unknown feature %d, continuing...\n", feat); | ||
| 476 | } | ||
| 477 | |||
| 478 | return 0; | ||
| 479 | } | ||
| 480 | |||
| 481 | int perf_header__read(struct perf_header *self, int fd) | ||
| 245 | { | 482 | { |
| 246 | struct perf_header *self = perf_header__new(); | ||
| 247 | struct perf_file_header f_header; | 483 | struct perf_file_header f_header; |
| 248 | struct perf_file_attr f_attr; | 484 | struct perf_file_attr f_attr; |
| 249 | u64 f_id; | 485 | u64 f_id; |
| 250 | |||
| 251 | int nr_attrs, nr_ids, i, j; | 486 | int nr_attrs, nr_ids, i, j; |
| 252 | 487 | ||
| 253 | lseek(fd, 0, SEEK_SET); | 488 | if (perf_file_header__read(&f_header, self, fd) < 0) { |
| 254 | do_read(fd, &f_header, sizeof(f_header)); | 489 | pr_debug("incompatible file format\n"); |
| 255 | 490 | return -EINVAL; | |
| 256 | if (f_header.magic != PERF_MAGIC || | 491 | } |
| 257 | f_header.size != sizeof(f_header) || | ||
| 258 | f_header.attr_size != sizeof(f_attr)) | ||
| 259 | die("incompatible file format"); | ||
| 260 | 492 | ||
| 261 | nr_attrs = f_header.attrs.size / sizeof(f_attr); | 493 | nr_attrs = f_header.attrs.size / sizeof(f_attr); |
| 262 | lseek(fd, f_header.attrs.offset, SEEK_SET); | 494 | lseek(fd, f_header.attrs.offset, SEEK_SET); |
| @@ -269,6 +501,8 @@ struct perf_header *perf_header__read(int fd) | |||
| 269 | tmp = lseek(fd, 0, SEEK_CUR); | 501 | tmp = lseek(fd, 0, SEEK_CUR); |
| 270 | 502 | ||
| 271 | attr = perf_header_attr__new(&f_attr.attr); | 503 | attr = perf_header_attr__new(&f_attr.attr); |
| 504 | if (attr == NULL) | ||
| 505 | return -ENOMEM; | ||
| 272 | 506 | ||
| 273 | nr_ids = f_attr.ids.size / sizeof(u64); | 507 | nr_ids = f_attr.ids.size / sizeof(u64); |
| 274 | lseek(fd, f_attr.ids.offset, SEEK_SET); | 508 | lseek(fd, f_attr.ids.offset, SEEK_SET); |
| @@ -276,31 +510,34 @@ struct perf_header *perf_header__read(int fd) | |||
| 276 | for (j = 0; j < nr_ids; j++) { | 510 | for (j = 0; j < nr_ids; j++) { |
| 277 | do_read(fd, &f_id, sizeof(f_id)); | 511 | do_read(fd, &f_id, sizeof(f_id)); |
| 278 | 512 | ||
| 279 | perf_header_attr__add_id(attr, f_id); | 513 | if (perf_header_attr__add_id(attr, f_id) < 0) { |
| 514 | perf_header_attr__delete(attr); | ||
| 515 | return -ENOMEM; | ||
| 516 | } | ||
| 280 | } | 517 | } |
| 281 | perf_header__add_attr(self, attr); | 518 | if (perf_header__add_attr(self, attr) < 0) { |
| 519 | perf_header_attr__delete(attr); | ||
| 520 | return -ENOMEM; | ||
| 521 | } | ||
| 522 | |||
| 282 | lseek(fd, tmp, SEEK_SET); | 523 | lseek(fd, tmp, SEEK_SET); |
| 283 | } | 524 | } |
| 284 | 525 | ||
| 285 | if (f_header.event_types.size) { | 526 | if (f_header.event_types.size) { |
| 286 | lseek(fd, f_header.event_types.offset, SEEK_SET); | 527 | lseek(fd, f_header.event_types.offset, SEEK_SET); |
| 287 | events = malloc(f_header.event_types.size); | 528 | events = malloc(f_header.event_types.size); |
| 288 | if (!events) | 529 | if (events == NULL) |
| 289 | die("nomem"); | 530 | return -ENOMEM; |
| 290 | do_read(fd, events, f_header.event_types.size); | 531 | do_read(fd, events, f_header.event_types.size); |
| 291 | event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); | 532 | event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); |
| 292 | } | 533 | } |
| 293 | self->event_offset = f_header.event_types.offset; | ||
| 294 | self->event_size = f_header.event_types.size; | ||
| 295 | 534 | ||
| 296 | self->data_offset = f_header.data.offset; | 535 | perf_header__process_sections(self, fd, perf_file_section__process); |
| 297 | self->data_size = f_header.data.size; | ||
| 298 | 536 | ||
| 299 | lseek(fd, self->data_offset, SEEK_SET); | 537 | lseek(fd, self->data_offset, SEEK_SET); |
| 300 | 538 | ||
| 301 | self->frozen = 1; | 539 | self->frozen = 1; |
| 302 | 540 | return 0; | |
| 303 | return self; | ||
| 304 | } | 541 | } |
| 305 | 542 | ||
| 306 | u64 perf_header__sample_type(struct perf_header *header) | 543 | u64 perf_header__sample_type(struct perf_header *header) |
