diff options
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 123 |
1 files changed, 69 insertions, 54 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 | ||