aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/header.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r--tools/perf/util/header.c123
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
131struct perf_file_section {
132 u64 offset;
133 u64 size;
134};
135
136struct perf_file_attr { 131struct 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
141struct 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
151void perf_header__set_feat(struct perf_header *self, int feat) 136void 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
327static void perf_header__adds_read(struct perf_header *self, int fd) 312int 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++]; 351int 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
379static 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
369struct perf_header *perf_header__read(int fd) 404struct 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