diff options
| -rw-r--r-- | tools/perf/util/header.c | 123 | ||||
| -rw-r--r-- | tools/perf/util/header.h | 31 |
2 files changed, 98 insertions, 56 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index ca0d657eefad..d8416f011179 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
| @@ -128,26 +128,11 @@ static const char *__perf_magic = "PERFFILE"; | |||
| 128 | 128 | ||
| 129 | #define PERF_MAGIC (*(u64 *)__perf_magic) | 129 | #define PERF_MAGIC (*(u64 *)__perf_magic) |
| 130 | 130 | ||
| 131 | struct perf_file_section { | ||
| 132 | u64 offset; | ||
| 133 | u64 size; | ||
| 134 | }; | ||
| 135 | |||
| 136 | struct perf_file_attr { | 131 | struct perf_file_attr { |
| 137 | struct perf_event_attr attr; | 132 | struct perf_event_attr attr; |
| 138 | struct perf_file_section ids; | 133 | struct perf_file_section ids; |
| 139 | }; | 134 | }; |
| 140 | 135 | ||
| 141 | struct perf_file_header { | ||
| 142 | u64 magic; | ||
| 143 | u64 size; | ||
| 144 | u64 attr_size; | ||
| 145 | struct perf_file_section attrs; | ||
| 146 | struct perf_file_section data; | ||
| 147 | struct perf_file_section event_types; | ||
| 148 | DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); | ||
| 149 | }; | ||
| 150 | |||
| 151 | void perf_header__set_feat(struct perf_header *self, int feat) | 136 | void perf_header__set_feat(struct perf_header *self, int feat) |
| 152 | { | 137 | { |
| 153 | set_bit(feat, self->adds_features); | 138 | set_bit(feat, self->adds_features); |
| @@ -324,21 +309,23 @@ static void do_read(int fd, void *buf, size_t size) | |||
| 324 | } | 309 | } |
| 325 | } | 310 | } |
| 326 | 311 | ||
| 327 | static void perf_header__adds_read(struct perf_header *self, int fd) | 312 | int perf_header__process_sections(struct perf_header *self, int fd, |
| 313 | int (*process)(struct perf_file_section *self, | ||
| 314 | int feat, int fd)) | ||
| 328 | { | 315 | { |
| 329 | struct perf_file_section *feat_sec; | 316 | struct perf_file_section *feat_sec; |
| 330 | int nr_sections; | 317 | int nr_sections; |
| 331 | int sec_size; | 318 | int sec_size; |
| 332 | int idx = 0; | 319 | int idx = 0; |
| 333 | 320 | int err = 0, feat = 1; | |
| 334 | 321 | ||
| 335 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | 322 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); |
| 336 | if (!nr_sections) | 323 | if (!nr_sections) |
| 337 | return; | 324 | return 0; |
| 338 | 325 | ||
| 339 | feat_sec = calloc(sizeof(*feat_sec), nr_sections); | 326 | feat_sec = calloc(sizeof(*feat_sec), nr_sections); |
| 340 | if (!feat_sec) | 327 | if (!feat_sec) |
| 341 | die("No memory"); | 328 | return -1; |
| 342 | 329 | ||
| 343 | sec_size = sizeof(*feat_sec) * nr_sections; | 330 | sec_size = sizeof(*feat_sec) * nr_sections; |
| 344 | 331 | ||
| @@ -346,25 +333,73 @@ static void perf_header__adds_read(struct perf_header *self, int fd) | |||
| 346 | 333 | ||
| 347 | do_read(fd, feat_sec, sec_size); | 334 | do_read(fd, feat_sec, sec_size); |
| 348 | 335 | ||
| 349 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { | 336 | while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { |
| 350 | struct perf_file_section *trace_sec; | 337 | if (perf_header__has_feat(self, feat)) { |
| 338 | struct perf_file_section *sec = &feat_sec[idx++]; | ||
| 351 | 339 | ||
| 352 | trace_sec = &feat_sec[idx++]; | 340 | err = process(sec, feat, fd); |
| 353 | lseek(fd, trace_sec->offset, SEEK_SET); | 341 | if (err < 0) |
| 354 | trace_report(fd); | 342 | break; |
| 343 | } | ||
| 344 | ++feat; | ||
| 355 | } | 345 | } |
| 356 | 346 | ||
| 357 | if (perf_header__has_feat(self, HEADER_BUILD_ID)) { | 347 | free(feat_sec); |
| 358 | struct perf_file_section *buildid_sec; | 348 | return err; |
| 349 | }; | ||
| 359 | 350 | ||
| 360 | buildid_sec = &feat_sec[idx++]; | 351 | int perf_file_header__read(struct perf_file_header *self, |
| 361 | lseek(fd, buildid_sec->offset, SEEK_SET); | 352 | struct perf_header *ph, int fd) |
| 362 | if (perf_header__read_build_ids(fd, buildid_sec->offset, buildid_sec->size)) | 353 | { |
| 363 | pr_debug("failed to read buildids, continuing...\n"); | 354 | lseek(fd, 0, SEEK_SET); |
| 355 | do_read(fd, self, sizeof(*self)); | ||
| 356 | |||
| 357 | if (self->magic != PERF_MAGIC || | ||
| 358 | self->attr_size != sizeof(struct perf_file_attr)) | ||
| 359 | return -1; | ||
| 360 | |||
| 361 | if (self->size != sizeof(*self)) { | ||
| 362 | /* Support the previous format */ | ||
| 363 | if (self->size == offsetof(typeof(*self), adds_features)) | ||
| 364 | bitmap_zero(self->adds_features, HEADER_FEAT_BITS); | ||
| 365 | else | ||
| 366 | return -1; | ||
| 364 | } | 367 | } |
| 365 | 368 | ||
| 366 | free(feat_sec); | 369 | memcpy(&ph->adds_features, &self->adds_features, |
| 367 | }; | 370 | sizeof(self->adds_features)); |
| 371 | |||
| 372 | ph->event_offset = self->event_types.offset; | ||
| 373 | ph->event_size = self->event_types.size; | ||
| 374 | ph->data_offset = self->data.offset; | ||
| 375 | ph->data_size = self->data.size; | ||
| 376 | return 0; | ||
| 377 | } | ||
| 378 | |||
| 379 | static int perf_file_section__process(struct perf_file_section *self, | ||
| 380 | int feat, int fd) | ||
| 381 | { | ||
| 382 | if (lseek(fd, self->offset, SEEK_SET) < 0) { | ||
| 383 | pr_debug("Failed to lseek to %Ld offset for feature %d, " | ||
| 384 | "continuing...\n", self->offset, feat); | ||
| 385 | return 0; | ||
| 386 | } | ||
| 387 | |||
| 388 | switch (feat) { | ||
| 389 | case HEADER_TRACE_INFO: | ||
| 390 | trace_report(fd); | ||
| 391 | break; | ||
| 392 | |||
| 393 | case HEADER_BUILD_ID: | ||
| 394 | if (perf_header__read_build_ids(fd, self->offset, self->size)) | ||
| 395 | pr_debug("Failed to read buildids, continuing...\n"); | ||
| 396 | break; | ||
| 397 | default: | ||
| 398 | pr_debug("unknown feature %d, continuing...\n", feat); | ||
| 399 | } | ||
| 400 | |||
| 401 | return 0; | ||
| 402 | } | ||
| 368 | 403 | ||
| 369 | struct perf_header *perf_header__read(int fd) | 404 | struct perf_header *perf_header__read(int fd) |
| 370 | { | 405 | { |
| @@ -372,23 +407,11 @@ struct perf_header *perf_header__read(int fd) | |||
| 372 | struct perf_file_header f_header; | 407 | struct perf_file_header f_header; |
| 373 | struct perf_file_attr f_attr; | 408 | struct perf_file_attr f_attr; |
| 374 | u64 f_id; | 409 | u64 f_id; |
| 375 | |||
| 376 | int nr_attrs, nr_ids, i, j; | 410 | int nr_attrs, nr_ids, i, j; |
| 377 | 411 | ||
| 378 | lseek(fd, 0, SEEK_SET); | 412 | if (perf_file_header__read(&f_header, self, fd) < 0) |
| 379 | do_read(fd, &f_header, sizeof(f_header)); | ||
| 380 | |||
| 381 | if (f_header.magic != PERF_MAGIC || | ||
| 382 | f_header.attr_size != sizeof(f_attr)) | ||
| 383 | die("incompatible file format"); | 413 | die("incompatible file format"); |
| 384 | 414 | ||
| 385 | if (f_header.size != sizeof(f_header)) { | ||
| 386 | /* Support the previous format */ | ||
| 387 | if (f_header.size == offsetof(typeof(f_header), adds_features)) | ||
| 388 | bitmap_zero(f_header.adds_features, HEADER_FEAT_BITS); | ||
| 389 | else | ||
| 390 | die("incompatible file format"); | ||
| 391 | } | ||
| 392 | nr_attrs = f_header.attrs.size / sizeof(f_attr); | 415 | nr_attrs = f_header.attrs.size / sizeof(f_attr); |
| 393 | lseek(fd, f_header.attrs.offset, SEEK_SET); | 416 | lseek(fd, f_header.attrs.offset, SEEK_SET); |
| 394 | 417 | ||
| @@ -422,15 +445,7 @@ struct perf_header *perf_header__read(int fd) | |||
| 422 | event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); | 445 | event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); |
| 423 | } | 446 | } |
| 424 | 447 | ||
| 425 | memcpy(&self->adds_features, &f_header.adds_features, sizeof(f_header.adds_features)); | 448 | perf_header__process_sections(self, fd, perf_file_section__process); |
| 426 | |||
| 427 | self->event_offset = f_header.event_types.offset; | ||
| 428 | self->event_size = f_header.event_types.size; | ||
| 429 | |||
| 430 | self->data_offset = f_header.data.offset; | ||
| 431 | self->data_size = f_header.data.size; | ||
| 432 | |||
| 433 | perf_header__adds_read(self, fd); | ||
| 434 | 449 | ||
| 435 | lseek(fd, self->data_offset, SEEK_SET); | 450 | lseek(fd, self->data_offset, SEEK_SET); |
| 436 | 451 | ||
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index a22d70b07571..f1b3bf7bdfc1 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h | |||
| @@ -15,11 +15,34 @@ struct perf_header_attr { | |||
| 15 | off_t id_offset; | 15 | off_t id_offset; |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | #define HEADER_TRACE_INFO 1 | 18 | enum { |
| 19 | #define HEADER_BUILD_ID 2 | 19 | HEADER_TRACE_INFO = 1, |
| 20 | HEADER_BUILD_ID, | ||
| 21 | HEADER_LAST_FEATURE, | ||
| 22 | }; | ||
| 20 | 23 | ||
| 21 | #define HEADER_FEAT_BITS 256 | 24 | #define HEADER_FEAT_BITS 256 |
| 22 | 25 | ||
| 26 | struct perf_file_section { | ||
| 27 | u64 offset; | ||
| 28 | u64 size; | ||
| 29 | }; | ||
| 30 | |||
| 31 | struct perf_file_header { | ||
| 32 | u64 magic; | ||
| 33 | u64 size; | ||
| 34 | u64 attr_size; | ||
| 35 | struct perf_file_section attrs; | ||
| 36 | struct perf_file_section data; | ||
| 37 | struct perf_file_section event_types; | ||
| 38 | DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); | ||
| 39 | }; | ||
| 40 | |||
| 41 | struct perf_header; | ||
| 42 | |||
| 43 | int perf_file_header__read(struct perf_file_header *self, | ||
| 44 | struct perf_header *ph, int fd); | ||
| 45 | |||
| 23 | struct perf_header { | 46 | struct perf_header { |
| 24 | int frozen; | 47 | int frozen; |
| 25 | int attrs, size; | 48 | int attrs, size; |
| @@ -54,4 +77,8 @@ bool perf_header__has_feat(const struct perf_header *self, int feat); | |||
| 54 | 77 | ||
| 55 | struct perf_header *perf_header__new(void); | 78 | struct perf_header *perf_header__new(void); |
| 56 | 79 | ||
| 80 | int perf_header__process_sections(struct perf_header *self, int fd, | ||
| 81 | int (*process)(struct perf_file_section *self, | ||
| 82 | int feat, int fd)); | ||
| 83 | |||
| 57 | #endif /* __PERF_HEADER_H */ | 84 | #endif /* __PERF_HEADER_H */ |
