diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-15 21:31:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-15 21:31:30 -0400 |
commit | a926021cb1f8a99a275eaf6eb546102e9469dc59 (patch) | |
tree | c6d0300cd4b1a1fd658708476db4577b68b4de31 /tools/perf/util/header.c | |
parent | 0586bed3e8563c2eb89bc7256e30ce633ae06cfb (diff) | |
parent | 5e814dd597c42daeb8d2a276e64a6ec986ad0e2a (diff) |
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (184 commits)
perf probe: Clean up probe_point_lazy_walker() return value
tracing: Fix irqoff selftest expanding max buffer
tracing: Align 4 byte ints together in struct tracer
tracing: Export trace_set_clr_event()
tracing: Explain about unstable clock on resume with ring buffer warning
ftrace/graph: Trace function entry before updating index
ftrace: Add .ref.text as one of the safe areas to trace
tracing: Adjust conditional expression latency formatting.
tracing: Fix event alignment: skb:kfree_skb
tracing: Fix event alignment: mce:mce_record
tracing: Fix event alignment: kvm:kvm_hv_hypercall
tracing: Fix event alignment: module:module_request
tracing: Fix event alignment: ftrace:context_switch and ftrace:wakeup
tracing: Remove lock_depth from event entry
perf header: Stop using 'self'
perf session: Use evlist/evsel for managing perf.data attributes
perf top: Don't let events to eat up whole header line
perf top: Fix events overflow in top command
ring-buffer: Remove unused #include <linux/trace_irq.h>
tracing: Add an 'overwrite' trace_option.
...
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 535 |
1 files changed, 226 insertions, 309 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 0866bcdb5e8e..e5230c0ef95b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -8,6 +8,8 @@ | |||
8 | #include <linux/list.h> | 8 | #include <linux/list.h> |
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | 10 | ||
11 | #include "evlist.h" | ||
12 | #include "evsel.h" | ||
11 | #include "util.h" | 13 | #include "util.h" |
12 | #include "header.h" | 14 | #include "header.h" |
13 | #include "../perf.h" | 15 | #include "../perf.h" |
@@ -18,89 +20,6 @@ | |||
18 | 20 | ||
19 | static bool no_buildid_cache = false; | 21 | static bool no_buildid_cache = false; |
20 | 22 | ||
21 | /* | ||
22 | * Create new perf.data header attribute: | ||
23 | */ | ||
24 | struct perf_header_attr *perf_header_attr__new(struct perf_event_attr *attr) | ||
25 | { | ||
26 | struct perf_header_attr *self = malloc(sizeof(*self)); | ||
27 | |||
28 | if (self != NULL) { | ||
29 | self->attr = *attr; | ||
30 | self->ids = 0; | ||
31 | self->size = 1; | ||
32 | self->id = malloc(sizeof(u64)); | ||
33 | if (self->id == NULL) { | ||
34 | free(self); | ||
35 | self = NULL; | ||
36 | } | ||
37 | } | ||
38 | |||
39 | return self; | ||
40 | } | ||
41 | |||
42 | void perf_header_attr__delete(struct perf_header_attr *self) | ||
43 | { | ||
44 | free(self->id); | ||
45 | free(self); | ||
46 | } | ||
47 | |||
48 | int perf_header_attr__add_id(struct perf_header_attr *self, u64 id) | ||
49 | { | ||
50 | int pos = self->ids; | ||
51 | |||
52 | self->ids++; | ||
53 | if (self->ids > self->size) { | ||
54 | int nsize = self->size * 2; | ||
55 | u64 *nid = realloc(self->id, nsize * sizeof(u64)); | ||
56 | |||
57 | if (nid == NULL) | ||
58 | return -1; | ||
59 | |||
60 | self->size = nsize; | ||
61 | self->id = nid; | ||
62 | } | ||
63 | self->id[pos] = id; | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | int perf_header__init(struct perf_header *self) | ||
68 | { | ||
69 | self->size = 1; | ||
70 | self->attr = malloc(sizeof(void *)); | ||
71 | return self->attr == NULL ? -ENOMEM : 0; | ||
72 | } | ||
73 | |||
74 | void perf_header__exit(struct perf_header *self) | ||
75 | { | ||
76 | int i; | ||
77 | for (i = 0; i < self->attrs; ++i) | ||
78 | perf_header_attr__delete(self->attr[i]); | ||
79 | free(self->attr); | ||
80 | } | ||
81 | |||
82 | int perf_header__add_attr(struct perf_header *self, | ||
83 | struct perf_header_attr *attr) | ||
84 | { | ||
85 | if (self->frozen) | ||
86 | return -1; | ||
87 | |||
88 | if (self->attrs == self->size) { | ||
89 | int nsize = self->size * 2; | ||
90 | struct perf_header_attr **nattr; | ||
91 | |||
92 | nattr = realloc(self->attr, nsize * sizeof(void *)); | ||
93 | if (nattr == NULL) | ||
94 | return -1; | ||
95 | |||
96 | self->size = nsize; | ||
97 | self->attr = nattr; | ||
98 | } | ||
99 | |||
100 | self->attr[self->attrs++] = attr; | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int event_count; | 23 | static int event_count; |
105 | static struct perf_trace_event_type *events; | 24 | static struct perf_trace_event_type *events; |
106 | 25 | ||
@@ -147,19 +66,19 @@ struct perf_file_attr { | |||
147 | struct perf_file_section ids; | 66 | struct perf_file_section ids; |
148 | }; | 67 | }; |
149 | 68 | ||
150 | void perf_header__set_feat(struct perf_header *self, int feat) | 69 | void perf_header__set_feat(struct perf_header *header, int feat) |
151 | { | 70 | { |
152 | set_bit(feat, self->adds_features); | 71 | set_bit(feat, header->adds_features); |
153 | } | 72 | } |
154 | 73 | ||
155 | void perf_header__clear_feat(struct perf_header *self, int feat) | 74 | void perf_header__clear_feat(struct perf_header *header, int feat) |
156 | { | 75 | { |
157 | clear_bit(feat, self->adds_features); | 76 | clear_bit(feat, header->adds_features); |
158 | } | 77 | } |
159 | 78 | ||
160 | bool perf_header__has_feat(const struct perf_header *self, int feat) | 79 | bool perf_header__has_feat(const struct perf_header *header, int feat) |
161 | { | 80 | { |
162 | return test_bit(feat, self->adds_features); | 81 | return test_bit(feat, header->adds_features); |
163 | } | 82 | } |
164 | 83 | ||
165 | static int do_write(int fd, const void *buf, size_t size) | 84 | static int do_write(int fd, const void *buf, size_t size) |
@@ -228,22 +147,22 @@ static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, | |||
228 | return 0; | 147 | return 0; |
229 | } | 148 | } |
230 | 149 | ||
231 | static int machine__write_buildid_table(struct machine *self, int fd) | 150 | static int machine__write_buildid_table(struct machine *machine, int fd) |
232 | { | 151 | { |
233 | int err; | 152 | int err; |
234 | u16 kmisc = PERF_RECORD_MISC_KERNEL, | 153 | u16 kmisc = PERF_RECORD_MISC_KERNEL, |
235 | umisc = PERF_RECORD_MISC_USER; | 154 | umisc = PERF_RECORD_MISC_USER; |
236 | 155 | ||
237 | if (!machine__is_host(self)) { | 156 | if (!machine__is_host(machine)) { |
238 | kmisc = PERF_RECORD_MISC_GUEST_KERNEL; | 157 | kmisc = PERF_RECORD_MISC_GUEST_KERNEL; |
239 | umisc = PERF_RECORD_MISC_GUEST_USER; | 158 | umisc = PERF_RECORD_MISC_GUEST_USER; |
240 | } | 159 | } |
241 | 160 | ||
242 | err = __dsos__write_buildid_table(&self->kernel_dsos, self->pid, | 161 | err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid, |
243 | kmisc, fd); | 162 | kmisc, fd); |
244 | if (err == 0) | 163 | if (err == 0) |
245 | err = __dsos__write_buildid_table(&self->user_dsos, | 164 | err = __dsos__write_buildid_table(&machine->user_dsos, |
246 | self->pid, umisc, fd); | 165 | machine->pid, umisc, fd); |
247 | return err; | 166 | return err; |
248 | } | 167 | } |
249 | 168 | ||
@@ -366,12 +285,12 @@ out_free: | |||
366 | return err; | 285 | return err; |
367 | } | 286 | } |
368 | 287 | ||
369 | static int dso__cache_build_id(struct dso *self, const char *debugdir) | 288 | static int dso__cache_build_id(struct dso *dso, const char *debugdir) |
370 | { | 289 | { |
371 | bool is_kallsyms = self->kernel && self->long_name[0] != '/'; | 290 | bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; |
372 | 291 | ||
373 | return build_id_cache__add_b(self->build_id, sizeof(self->build_id), | 292 | return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), |
374 | self->long_name, debugdir, is_kallsyms); | 293 | dso->long_name, debugdir, is_kallsyms); |
375 | } | 294 | } |
376 | 295 | ||
377 | static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) | 296 | static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) |
@@ -386,14 +305,14 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) | |||
386 | return err; | 305 | return err; |
387 | } | 306 | } |
388 | 307 | ||
389 | static int machine__cache_build_ids(struct machine *self, const char *debugdir) | 308 | static int machine__cache_build_ids(struct machine *machine, const char *debugdir) |
390 | { | 309 | { |
391 | int ret = __dsos__cache_build_ids(&self->kernel_dsos, debugdir); | 310 | int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir); |
392 | ret |= __dsos__cache_build_ids(&self->user_dsos, debugdir); | 311 | ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir); |
393 | return ret; | 312 | return ret; |
394 | } | 313 | } |
395 | 314 | ||
396 | static int perf_session__cache_build_ids(struct perf_session *self) | 315 | static int perf_session__cache_build_ids(struct perf_session *session) |
397 | { | 316 | { |
398 | struct rb_node *nd; | 317 | struct rb_node *nd; |
399 | int ret; | 318 | int ret; |
@@ -404,28 +323,28 @@ static int perf_session__cache_build_ids(struct perf_session *self) | |||
404 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) | 323 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) |
405 | return -1; | 324 | return -1; |
406 | 325 | ||
407 | ret = machine__cache_build_ids(&self->host_machine, debugdir); | 326 | ret = machine__cache_build_ids(&session->host_machine, debugdir); |
408 | 327 | ||
409 | for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) { | 328 | for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { |
410 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | 329 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
411 | ret |= machine__cache_build_ids(pos, debugdir); | 330 | ret |= machine__cache_build_ids(pos, debugdir); |
412 | } | 331 | } |
413 | return ret ? -1 : 0; | 332 | return ret ? -1 : 0; |
414 | } | 333 | } |
415 | 334 | ||
416 | static bool machine__read_build_ids(struct machine *self, bool with_hits) | 335 | static bool machine__read_build_ids(struct machine *machine, bool with_hits) |
417 | { | 336 | { |
418 | bool ret = __dsos__read_build_ids(&self->kernel_dsos, with_hits); | 337 | bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits); |
419 | ret |= __dsos__read_build_ids(&self->user_dsos, with_hits); | 338 | ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits); |
420 | return ret; | 339 | return ret; |
421 | } | 340 | } |
422 | 341 | ||
423 | static bool perf_session__read_build_ids(struct perf_session *self, bool with_hits) | 342 | static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits) |
424 | { | 343 | { |
425 | struct rb_node *nd; | 344 | struct rb_node *nd; |
426 | bool ret = machine__read_build_ids(&self->host_machine, with_hits); | 345 | bool ret = machine__read_build_ids(&session->host_machine, with_hits); |
427 | 346 | ||
428 | for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) { | 347 | for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { |
429 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | 348 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
430 | ret |= machine__read_build_ids(pos, with_hits); | 349 | ret |= machine__read_build_ids(pos, with_hits); |
431 | } | 350 | } |
@@ -433,7 +352,8 @@ static bool perf_session__read_build_ids(struct perf_session *self, bool with_hi | |||
433 | return ret; | 352 | return ret; |
434 | } | 353 | } |
435 | 354 | ||
436 | static int perf_header__adds_write(struct perf_header *self, int fd) | 355 | static int perf_header__adds_write(struct perf_header *header, |
356 | struct perf_evlist *evlist, int fd) | ||
437 | { | 357 | { |
438 | int nr_sections; | 358 | int nr_sections; |
439 | struct perf_session *session; | 359 | struct perf_session *session; |
@@ -442,13 +362,13 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
442 | u64 sec_start; | 362 | u64 sec_start; |
443 | int idx = 0, err; | 363 | int idx = 0, err; |
444 | 364 | ||
445 | session = container_of(self, struct perf_session, header); | 365 | session = container_of(header, struct perf_session, header); |
446 | 366 | ||
447 | if (perf_header__has_feat(self, HEADER_BUILD_ID && | 367 | if (perf_header__has_feat(header, HEADER_BUILD_ID && |
448 | !perf_session__read_build_ids(session, true))) | 368 | !perf_session__read_build_ids(session, true))) |
449 | perf_header__clear_feat(self, HEADER_BUILD_ID); | 369 | perf_header__clear_feat(header, HEADER_BUILD_ID); |
450 | 370 | ||
451 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | 371 | nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); |
452 | if (!nr_sections) | 372 | if (!nr_sections) |
453 | return 0; | 373 | return 0; |
454 | 374 | ||
@@ -458,28 +378,28 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
458 | 378 | ||
459 | sec_size = sizeof(*feat_sec) * nr_sections; | 379 | sec_size = sizeof(*feat_sec) * nr_sections; |
460 | 380 | ||
461 | sec_start = self->data_offset + self->data_size; | 381 | sec_start = header->data_offset + header->data_size; |
462 | lseek(fd, sec_start + sec_size, SEEK_SET); | 382 | lseek(fd, sec_start + sec_size, SEEK_SET); |
463 | 383 | ||
464 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { | 384 | if (perf_header__has_feat(header, HEADER_TRACE_INFO)) { |
465 | struct perf_file_section *trace_sec; | 385 | struct perf_file_section *trace_sec; |
466 | 386 | ||
467 | trace_sec = &feat_sec[idx++]; | 387 | trace_sec = &feat_sec[idx++]; |
468 | 388 | ||
469 | /* Write trace info */ | 389 | /* Write trace info */ |
470 | trace_sec->offset = lseek(fd, 0, SEEK_CUR); | 390 | trace_sec->offset = lseek(fd, 0, SEEK_CUR); |
471 | read_tracing_data(fd, &evsel_list); | 391 | read_tracing_data(fd, &evlist->entries); |
472 | trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; | 392 | trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; |
473 | } | 393 | } |
474 | 394 | ||
475 | if (perf_header__has_feat(self, HEADER_BUILD_ID)) { | 395 | if (perf_header__has_feat(header, HEADER_BUILD_ID)) { |
476 | struct perf_file_section *buildid_sec; | 396 | struct perf_file_section *buildid_sec; |
477 | 397 | ||
478 | buildid_sec = &feat_sec[idx++]; | 398 | buildid_sec = &feat_sec[idx++]; |
479 | 399 | ||
480 | /* Write build-ids */ | 400 | /* Write build-ids */ |
481 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); | 401 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); |
482 | err = dsos__write_buildid_table(self, fd); | 402 | err = dsos__write_buildid_table(header, fd); |
483 | if (err < 0) { | 403 | if (err < 0) { |
484 | pr_debug("failed to write buildid table\n"); | 404 | pr_debug("failed to write buildid table\n"); |
485 | goto out_free; | 405 | goto out_free; |
@@ -518,32 +438,41 @@ int perf_header__write_pipe(int fd) | |||
518 | return 0; | 438 | return 0; |
519 | } | 439 | } |
520 | 440 | ||
521 | int perf_header__write(struct perf_header *self, int fd, bool at_exit) | 441 | int perf_session__write_header(struct perf_session *session, |
442 | struct perf_evlist *evlist, | ||
443 | int fd, bool at_exit) | ||
522 | { | 444 | { |
523 | struct perf_file_header f_header; | 445 | struct perf_file_header f_header; |
524 | struct perf_file_attr f_attr; | 446 | struct perf_file_attr f_attr; |
525 | struct perf_header_attr *attr; | 447 | struct perf_header *header = &session->header; |
526 | int i, err; | 448 | struct perf_evsel *attr, *pair = NULL; |
449 | int err; | ||
527 | 450 | ||
528 | lseek(fd, sizeof(f_header), SEEK_SET); | 451 | lseek(fd, sizeof(f_header), SEEK_SET); |
529 | 452 | ||
530 | for (i = 0; i < self->attrs; i++) { | 453 | if (session->evlist != evlist) |
531 | attr = self->attr[i]; | 454 | pair = list_entry(session->evlist->entries.next, struct perf_evsel, node); |
532 | 455 | ||
456 | list_for_each_entry(attr, &evlist->entries, node) { | ||
533 | attr->id_offset = lseek(fd, 0, SEEK_CUR); | 457 | attr->id_offset = lseek(fd, 0, SEEK_CUR); |
534 | err = do_write(fd, attr->id, attr->ids * sizeof(u64)); | 458 | err = do_write(fd, attr->id, attr->ids * sizeof(u64)); |
535 | if (err < 0) { | 459 | if (err < 0) { |
460 | out_err_write: | ||
536 | pr_debug("failed to write perf header\n"); | 461 | pr_debug("failed to write perf header\n"); |
537 | return err; | 462 | return err; |
538 | } | 463 | } |
464 | if (session->evlist != evlist) { | ||
465 | err = do_write(fd, pair->id, pair->ids * sizeof(u64)); | ||
466 | if (err < 0) | ||
467 | goto out_err_write; | ||
468 | attr->ids += pair->ids; | ||
469 | pair = list_entry(pair->node.next, struct perf_evsel, node); | ||
470 | } | ||
539 | } | 471 | } |
540 | 472 | ||
473 | header->attr_offset = lseek(fd, 0, SEEK_CUR); | ||
541 | 474 | ||
542 | self->attr_offset = lseek(fd, 0, SEEK_CUR); | 475 | list_for_each_entry(attr, &evlist->entries, node) { |
543 | |||
544 | for (i = 0; i < self->attrs; i++) { | ||
545 | attr = self->attr[i]; | ||
546 | |||
547 | f_attr = (struct perf_file_attr){ | 476 | f_attr = (struct perf_file_attr){ |
548 | .attr = attr->attr, | 477 | .attr = attr->attr, |
549 | .ids = { | 478 | .ids = { |
@@ -558,20 +487,20 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
558 | } | 487 | } |
559 | } | 488 | } |
560 | 489 | ||
561 | self->event_offset = lseek(fd, 0, SEEK_CUR); | 490 | header->event_offset = lseek(fd, 0, SEEK_CUR); |
562 | self->event_size = event_count * sizeof(struct perf_trace_event_type); | 491 | header->event_size = event_count * sizeof(struct perf_trace_event_type); |
563 | if (events) { | 492 | if (events) { |
564 | err = do_write(fd, events, self->event_size); | 493 | err = do_write(fd, events, header->event_size); |
565 | if (err < 0) { | 494 | if (err < 0) { |
566 | pr_debug("failed to write perf header events\n"); | 495 | pr_debug("failed to write perf header events\n"); |
567 | return err; | 496 | return err; |
568 | } | 497 | } |
569 | } | 498 | } |
570 | 499 | ||
571 | self->data_offset = lseek(fd, 0, SEEK_CUR); | 500 | header->data_offset = lseek(fd, 0, SEEK_CUR); |
572 | 501 | ||
573 | if (at_exit) { | 502 | if (at_exit) { |
574 | err = perf_header__adds_write(self, fd); | 503 | err = perf_header__adds_write(header, evlist, fd); |
575 | if (err < 0) | 504 | if (err < 0) |
576 | return err; | 505 | return err; |
577 | } | 506 | } |
@@ -581,20 +510,20 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
581 | .size = sizeof(f_header), | 510 | .size = sizeof(f_header), |
582 | .attr_size = sizeof(f_attr), | 511 | .attr_size = sizeof(f_attr), |
583 | .attrs = { | 512 | .attrs = { |
584 | .offset = self->attr_offset, | 513 | .offset = header->attr_offset, |
585 | .size = self->attrs * sizeof(f_attr), | 514 | .size = evlist->nr_entries * sizeof(f_attr), |
586 | }, | 515 | }, |
587 | .data = { | 516 | .data = { |
588 | .offset = self->data_offset, | 517 | .offset = header->data_offset, |
589 | .size = self->data_size, | 518 | .size = header->data_size, |
590 | }, | 519 | }, |
591 | .event_types = { | 520 | .event_types = { |
592 | .offset = self->event_offset, | 521 | .offset = header->event_offset, |
593 | .size = self->event_size, | 522 | .size = header->event_size, |
594 | }, | 523 | }, |
595 | }; | 524 | }; |
596 | 525 | ||
597 | memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features)); | 526 | memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features)); |
598 | 527 | ||
599 | lseek(fd, 0, SEEK_SET); | 528 | lseek(fd, 0, SEEK_SET); |
600 | err = do_write(fd, &f_header, sizeof(f_header)); | 529 | err = do_write(fd, &f_header, sizeof(f_header)); |
@@ -602,26 +531,26 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
602 | pr_debug("failed to write perf header\n"); | 531 | pr_debug("failed to write perf header\n"); |
603 | return err; | 532 | return err; |
604 | } | 533 | } |
605 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | 534 | lseek(fd, header->data_offset + header->data_size, SEEK_SET); |
606 | 535 | ||
607 | self->frozen = 1; | 536 | header->frozen = 1; |
608 | return 0; | 537 | return 0; |
609 | } | 538 | } |
610 | 539 | ||
611 | static int perf_header__getbuffer64(struct perf_header *self, | 540 | static int perf_header__getbuffer64(struct perf_header *header, |
612 | int fd, void *buf, size_t size) | 541 | int fd, void *buf, size_t size) |
613 | { | 542 | { |
614 | if (readn(fd, buf, size) <= 0) | 543 | if (readn(fd, buf, size) <= 0) |
615 | return -1; | 544 | return -1; |
616 | 545 | ||
617 | if (self->needs_swap) | 546 | if (header->needs_swap) |
618 | mem_bswap_64(buf, size); | 547 | mem_bswap_64(buf, size); |
619 | 548 | ||
620 | return 0; | 549 | return 0; |
621 | } | 550 | } |
622 | 551 | ||
623 | int perf_header__process_sections(struct perf_header *self, int fd, | 552 | int perf_header__process_sections(struct perf_header *header, int fd, |
624 | int (*process)(struct perf_file_section *self, | 553 | int (*process)(struct perf_file_section *section, |
625 | struct perf_header *ph, | 554 | struct perf_header *ph, |
626 | int feat, int fd)) | 555 | int feat, int fd)) |
627 | { | 556 | { |
@@ -631,7 +560,7 @@ int perf_header__process_sections(struct perf_header *self, int fd, | |||
631 | int idx = 0; | 560 | int idx = 0; |
632 | int err = -1, feat = 1; | 561 | int err = -1, feat = 1; |
633 | 562 | ||
634 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | 563 | nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); |
635 | if (!nr_sections) | 564 | if (!nr_sections) |
636 | return 0; | 565 | return 0; |
637 | 566 | ||
@@ -641,17 +570,17 @@ int perf_header__process_sections(struct perf_header *self, int fd, | |||
641 | 570 | ||
642 | sec_size = sizeof(*feat_sec) * nr_sections; | 571 | sec_size = sizeof(*feat_sec) * nr_sections; |
643 | 572 | ||
644 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | 573 | lseek(fd, header->data_offset + header->data_size, SEEK_SET); |
645 | 574 | ||
646 | if (perf_header__getbuffer64(self, fd, feat_sec, sec_size)) | 575 | if (perf_header__getbuffer64(header, fd, feat_sec, sec_size)) |
647 | goto out_free; | 576 | goto out_free; |
648 | 577 | ||
649 | err = 0; | 578 | err = 0; |
650 | while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { | 579 | while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { |
651 | if (perf_header__has_feat(self, feat)) { | 580 | if (perf_header__has_feat(header, feat)) { |
652 | struct perf_file_section *sec = &feat_sec[idx++]; | 581 | struct perf_file_section *sec = &feat_sec[idx++]; |
653 | 582 | ||
654 | err = process(sec, self, feat, fd); | 583 | err = process(sec, header, feat, fd); |
655 | if (err < 0) | 584 | if (err < 0) |
656 | break; | 585 | break; |
657 | } | 586 | } |
@@ -662,35 +591,35 @@ out_free: | |||
662 | return err; | 591 | return err; |
663 | } | 592 | } |
664 | 593 | ||
665 | int perf_file_header__read(struct perf_file_header *self, | 594 | int perf_file_header__read(struct perf_file_header *header, |
666 | struct perf_header *ph, int fd) | 595 | struct perf_header *ph, int fd) |
667 | { | 596 | { |
668 | lseek(fd, 0, SEEK_SET); | 597 | lseek(fd, 0, SEEK_SET); |
669 | 598 | ||
670 | if (readn(fd, self, sizeof(*self)) <= 0 || | 599 | if (readn(fd, header, sizeof(*header)) <= 0 || |
671 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | 600 | memcmp(&header->magic, __perf_magic, sizeof(header->magic))) |
672 | return -1; | 601 | return -1; |
673 | 602 | ||
674 | if (self->attr_size != sizeof(struct perf_file_attr)) { | 603 | if (header->attr_size != sizeof(struct perf_file_attr)) { |
675 | u64 attr_size = bswap_64(self->attr_size); | 604 | u64 attr_size = bswap_64(header->attr_size); |
676 | 605 | ||
677 | if (attr_size != sizeof(struct perf_file_attr)) | 606 | if (attr_size != sizeof(struct perf_file_attr)) |
678 | return -1; | 607 | return -1; |
679 | 608 | ||
680 | mem_bswap_64(self, offsetof(struct perf_file_header, | 609 | mem_bswap_64(header, offsetof(struct perf_file_header, |
681 | adds_features)); | 610 | adds_features)); |
682 | ph->needs_swap = true; | 611 | ph->needs_swap = true; |
683 | } | 612 | } |
684 | 613 | ||
685 | if (self->size != sizeof(*self)) { | 614 | if (header->size != sizeof(*header)) { |
686 | /* Support the previous format */ | 615 | /* Support the previous format */ |
687 | if (self->size == offsetof(typeof(*self), adds_features)) | 616 | if (header->size == offsetof(typeof(*header), adds_features)) |
688 | bitmap_zero(self->adds_features, HEADER_FEAT_BITS); | 617 | bitmap_zero(header->adds_features, HEADER_FEAT_BITS); |
689 | else | 618 | else |
690 | return -1; | 619 | return -1; |
691 | } | 620 | } |
692 | 621 | ||
693 | memcpy(&ph->adds_features, &self->adds_features, | 622 | memcpy(&ph->adds_features, &header->adds_features, |
694 | sizeof(ph->adds_features)); | 623 | sizeof(ph->adds_features)); |
695 | /* | 624 | /* |
696 | * FIXME: hack that assumes that if we need swap the perf.data file | 625 | * FIXME: hack that assumes that if we need swap the perf.data file |
@@ -704,10 +633,10 @@ int perf_file_header__read(struct perf_file_header *self, | |||
704 | perf_header__set_feat(ph, HEADER_BUILD_ID); | 633 | perf_header__set_feat(ph, HEADER_BUILD_ID); |
705 | } | 634 | } |
706 | 635 | ||
707 | ph->event_offset = self->event_types.offset; | 636 | ph->event_offset = header->event_types.offset; |
708 | ph->event_size = self->event_types.size; | 637 | ph->event_size = header->event_types.size; |
709 | ph->data_offset = self->data.offset; | 638 | ph->data_offset = header->data.offset; |
710 | ph->data_size = self->data.size; | 639 | ph->data_size = header->data.size; |
711 | return 0; | 640 | return 0; |
712 | } | 641 | } |
713 | 642 | ||
@@ -766,11 +695,10 @@ out: | |||
766 | return err; | 695 | return err; |
767 | } | 696 | } |
768 | 697 | ||
769 | static int perf_header__read_build_ids(struct perf_header *self, | 698 | static int perf_header__read_build_ids(struct perf_header *header, |
770 | int input, u64 offset, u64 size) | 699 | int input, u64 offset, u64 size) |
771 | { | 700 | { |
772 | struct perf_session *session = container_of(self, | 701 | struct perf_session *session = container_of(header, struct perf_session, header); |
773 | struct perf_session, header); | ||
774 | struct build_id_event bev; | 702 | struct build_id_event bev; |
775 | char filename[PATH_MAX]; | 703 | char filename[PATH_MAX]; |
776 | u64 limit = offset + size; | 704 | u64 limit = offset + size; |
@@ -782,7 +710,7 @@ static int perf_header__read_build_ids(struct perf_header *self, | |||
782 | if (read(input, &bev, sizeof(bev)) != sizeof(bev)) | 710 | if (read(input, &bev, sizeof(bev)) != sizeof(bev)) |
783 | goto out; | 711 | goto out; |
784 | 712 | ||
785 | if (self->needs_swap) | 713 | if (header->needs_swap) |
786 | perf_event_header__bswap(&bev.header); | 714 | perf_event_header__bswap(&bev.header); |
787 | 715 | ||
788 | len = bev.header.size - sizeof(bev); | 716 | len = bev.header.size - sizeof(bev); |
@@ -798,13 +726,13 @@ out: | |||
798 | return err; | 726 | return err; |
799 | } | 727 | } |
800 | 728 | ||
801 | static int perf_file_section__process(struct perf_file_section *self, | 729 | static int perf_file_section__process(struct perf_file_section *section, |
802 | struct perf_header *ph, | 730 | struct perf_header *ph, |
803 | int feat, int fd) | 731 | int feat, int fd) |
804 | { | 732 | { |
805 | if (lseek(fd, self->offset, SEEK_SET) == (off_t)-1) { | 733 | if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) { |
806 | pr_debug("Failed to lseek to %" PRIu64 " offset for feature " | 734 | pr_debug("Failed to lseek to %" PRIu64 " offset for feature " |
807 | "%d, continuing...\n", self->offset, feat); | 735 | "%d, continuing...\n", section->offset, feat); |
808 | return 0; | 736 | return 0; |
809 | } | 737 | } |
810 | 738 | ||
@@ -814,7 +742,7 @@ static int perf_file_section__process(struct perf_file_section *self, | |||
814 | break; | 742 | break; |
815 | 743 | ||
816 | case HEADER_BUILD_ID: | 744 | case HEADER_BUILD_ID: |
817 | if (perf_header__read_build_ids(ph, fd, self->offset, self->size)) | 745 | if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) |
818 | pr_debug("Failed to read buildids, continuing...\n"); | 746 | pr_debug("Failed to read buildids, continuing...\n"); |
819 | break; | 747 | break; |
820 | default: | 748 | default: |
@@ -824,21 +752,21 @@ static int perf_file_section__process(struct perf_file_section *self, | |||
824 | return 0; | 752 | return 0; |
825 | } | 753 | } |
826 | 754 | ||
827 | static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, | 755 | static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, |
828 | struct perf_header *ph, int fd, | 756 | struct perf_header *ph, int fd, |
829 | bool repipe) | 757 | bool repipe) |
830 | { | 758 | { |
831 | if (readn(fd, self, sizeof(*self)) <= 0 || | 759 | if (readn(fd, header, sizeof(*header)) <= 0 || |
832 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | 760 | memcmp(&header->magic, __perf_magic, sizeof(header->magic))) |
833 | return -1; | 761 | return -1; |
834 | 762 | ||
835 | if (repipe && do_write(STDOUT_FILENO, self, sizeof(*self)) < 0) | 763 | if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0) |
836 | return -1; | 764 | return -1; |
837 | 765 | ||
838 | if (self->size != sizeof(*self)) { | 766 | if (header->size != sizeof(*header)) { |
839 | u64 size = bswap_64(self->size); | 767 | u64 size = bswap_64(header->size); |
840 | 768 | ||
841 | if (size != sizeof(*self)) | 769 | if (size != sizeof(*header)) |
842 | return -1; | 770 | return -1; |
843 | 771 | ||
844 | ph->needs_swap = true; | 772 | ph->needs_swap = true; |
@@ -849,10 +777,10 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, | |||
849 | 777 | ||
850 | static int perf_header__read_pipe(struct perf_session *session, int fd) | 778 | static int perf_header__read_pipe(struct perf_session *session, int fd) |
851 | { | 779 | { |
852 | struct perf_header *self = &session->header; | 780 | struct perf_header *header = &session->header; |
853 | struct perf_pipe_file_header f_header; | 781 | struct perf_pipe_file_header f_header; |
854 | 782 | ||
855 | if (perf_file_header__read_pipe(&f_header, self, fd, | 783 | if (perf_file_header__read_pipe(&f_header, header, fd, |
856 | session->repipe) < 0) { | 784 | session->repipe) < 0) { |
857 | pr_debug("incompatible file format\n"); | 785 | pr_debug("incompatible file format\n"); |
858 | return -EINVAL; | 786 | return -EINVAL; |
@@ -863,18 +791,22 @@ static int perf_header__read_pipe(struct perf_session *session, int fd) | |||
863 | return 0; | 791 | return 0; |
864 | } | 792 | } |
865 | 793 | ||
866 | int perf_header__read(struct perf_session *session, int fd) | 794 | int perf_session__read_header(struct perf_session *session, int fd) |
867 | { | 795 | { |
868 | struct perf_header *self = &session->header; | 796 | struct perf_header *header = &session->header; |
869 | struct perf_file_header f_header; | 797 | struct perf_file_header f_header; |
870 | struct perf_file_attr f_attr; | 798 | struct perf_file_attr f_attr; |
871 | u64 f_id; | 799 | u64 f_id; |
872 | int nr_attrs, nr_ids, i, j; | 800 | int nr_attrs, nr_ids, i, j; |
873 | 801 | ||
802 | session->evlist = perf_evlist__new(NULL, NULL); | ||
803 | if (session->evlist == NULL) | ||
804 | return -ENOMEM; | ||
805 | |||
874 | if (session->fd_pipe) | 806 | if (session->fd_pipe) |
875 | return perf_header__read_pipe(session, fd); | 807 | return perf_header__read_pipe(session, fd); |
876 | 808 | ||
877 | if (perf_file_header__read(&f_header, self, fd) < 0) { | 809 | if (perf_file_header__read(&f_header, header, fd) < 0) { |
878 | pr_debug("incompatible file format\n"); | 810 | pr_debug("incompatible file format\n"); |
879 | return -EINVAL; | 811 | return -EINVAL; |
880 | } | 812 | } |
@@ -883,33 +815,39 @@ int perf_header__read(struct perf_session *session, int fd) | |||
883 | lseek(fd, f_header.attrs.offset, SEEK_SET); | 815 | lseek(fd, f_header.attrs.offset, SEEK_SET); |
884 | 816 | ||
885 | for (i = 0; i < nr_attrs; i++) { | 817 | for (i = 0; i < nr_attrs; i++) { |
886 | struct perf_header_attr *attr; | 818 | struct perf_evsel *evsel; |
887 | off_t tmp; | 819 | off_t tmp; |
888 | 820 | ||
889 | if (perf_header__getbuffer64(self, fd, &f_attr, sizeof(f_attr))) | 821 | if (perf_header__getbuffer64(header, fd, &f_attr, sizeof(f_attr))) |
890 | goto out_errno; | 822 | goto out_errno; |
891 | 823 | ||
892 | tmp = lseek(fd, 0, SEEK_CUR); | 824 | tmp = lseek(fd, 0, SEEK_CUR); |
825 | evsel = perf_evsel__new(&f_attr.attr, i); | ||
893 | 826 | ||
894 | attr = perf_header_attr__new(&f_attr.attr); | 827 | if (evsel == NULL) |
895 | if (attr == NULL) | 828 | goto out_delete_evlist; |
896 | return -ENOMEM; | 829 | /* |
830 | * Do it before so that if perf_evsel__alloc_id fails, this | ||
831 | * entry gets purged too at perf_evlist__delete(). | ||
832 | */ | ||
833 | perf_evlist__add(session->evlist, evsel); | ||
897 | 834 | ||
898 | nr_ids = f_attr.ids.size / sizeof(u64); | 835 | nr_ids = f_attr.ids.size / sizeof(u64); |
836 | /* | ||
837 | * We don't have the cpu and thread maps on the header, so | ||
838 | * for allocating the perf_sample_id table we fake 1 cpu and | ||
839 | * hattr->ids threads. | ||
840 | */ | ||
841 | if (perf_evsel__alloc_id(evsel, 1, nr_ids)) | ||
842 | goto out_delete_evlist; | ||
843 | |||
899 | lseek(fd, f_attr.ids.offset, SEEK_SET); | 844 | lseek(fd, f_attr.ids.offset, SEEK_SET); |
900 | 845 | ||
901 | for (j = 0; j < nr_ids; j++) { | 846 | for (j = 0; j < nr_ids; j++) { |
902 | if (perf_header__getbuffer64(self, fd, &f_id, sizeof(f_id))) | 847 | if (perf_header__getbuffer64(header, fd, &f_id, sizeof(f_id))) |
903 | goto out_errno; | 848 | goto out_errno; |
904 | 849 | ||
905 | if (perf_header_attr__add_id(attr, f_id) < 0) { | 850 | perf_evlist__id_add(session->evlist, evsel, 0, j, f_id); |
906 | perf_header_attr__delete(attr); | ||
907 | return -ENOMEM; | ||
908 | } | ||
909 | } | ||
910 | if (perf_header__add_attr(self, attr) < 0) { | ||
911 | perf_header_attr__delete(attr); | ||
912 | return -ENOMEM; | ||
913 | } | 851 | } |
914 | 852 | ||
915 | lseek(fd, tmp, SEEK_SET); | 853 | lseek(fd, tmp, SEEK_SET); |
@@ -920,93 +858,63 @@ int perf_header__read(struct perf_session *session, int fd) | |||
920 | events = malloc(f_header.event_types.size); | 858 | events = malloc(f_header.event_types.size); |
921 | if (events == NULL) | 859 | if (events == NULL) |
922 | return -ENOMEM; | 860 | return -ENOMEM; |
923 | if (perf_header__getbuffer64(self, fd, events, | 861 | if (perf_header__getbuffer64(header, fd, events, |
924 | f_header.event_types.size)) | 862 | f_header.event_types.size)) |
925 | goto out_errno; | 863 | goto out_errno; |
926 | event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); | 864 | event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); |
927 | } | 865 | } |
928 | 866 | ||
929 | perf_header__process_sections(self, fd, perf_file_section__process); | 867 | perf_header__process_sections(header, fd, perf_file_section__process); |
930 | 868 | ||
931 | lseek(fd, self->data_offset, SEEK_SET); | 869 | lseek(fd, header->data_offset, SEEK_SET); |
932 | 870 | ||
933 | self->frozen = 1; | 871 | header->frozen = 1; |
934 | return 0; | 872 | return 0; |
935 | out_errno: | 873 | out_errno: |
936 | return -errno; | 874 | return -errno; |
875 | |||
876 | out_delete_evlist: | ||
877 | perf_evlist__delete(session->evlist); | ||
878 | session->evlist = NULL; | ||
879 | return -ENOMEM; | ||
937 | } | 880 | } |
938 | 881 | ||
939 | u64 perf_header__sample_type(struct perf_header *header) | 882 | u64 perf_evlist__sample_type(struct perf_evlist *evlist) |
940 | { | 883 | { |
884 | struct perf_evsel *pos; | ||
941 | u64 type = 0; | 885 | u64 type = 0; |
942 | int i; | ||
943 | |||
944 | for (i = 0; i < header->attrs; i++) { | ||
945 | struct perf_header_attr *attr = header->attr[i]; | ||
946 | 886 | ||
887 | list_for_each_entry(pos, &evlist->entries, node) { | ||
947 | if (!type) | 888 | if (!type) |
948 | type = attr->attr.sample_type; | 889 | type = pos->attr.sample_type; |
949 | else if (type != attr->attr.sample_type) | 890 | else if (type != pos->attr.sample_type) |
950 | die("non matching sample_type"); | 891 | die("non matching sample_type"); |
951 | } | 892 | } |
952 | 893 | ||
953 | return type; | 894 | return type; |
954 | } | 895 | } |
955 | 896 | ||
956 | bool perf_header__sample_id_all(const struct perf_header *header) | 897 | bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) |
957 | { | 898 | { |
958 | bool value = false, first = true; | 899 | bool value = false, first = true; |
959 | int i; | 900 | struct perf_evsel *pos; |
960 | |||
961 | for (i = 0; i < header->attrs; i++) { | ||
962 | struct perf_header_attr *attr = header->attr[i]; | ||
963 | 901 | ||
902 | list_for_each_entry(pos, &evlist->entries, node) { | ||
964 | if (first) { | 903 | if (first) { |
965 | value = attr->attr.sample_id_all; | 904 | value = pos->attr.sample_id_all; |
966 | first = false; | 905 | first = false; |
967 | } else if (value != attr->attr.sample_id_all) | 906 | } else if (value != pos->attr.sample_id_all) |
968 | die("non matching sample_id_all"); | 907 | die("non matching sample_id_all"); |
969 | } | 908 | } |
970 | 909 | ||
971 | return value; | 910 | return value; |
972 | } | 911 | } |
973 | 912 | ||
974 | struct perf_event_attr * | 913 | int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, |
975 | perf_header__find_attr(u64 id, struct perf_header *header) | 914 | perf_event__handler_t process, |
976 | { | 915 | struct perf_session *session) |
977 | int i; | ||
978 | |||
979 | /* | ||
980 | * We set id to -1 if the data file doesn't contain sample | ||
981 | * ids. This can happen when the data file contains one type | ||
982 | * of event and in that case, the header can still store the | ||
983 | * event attribute information. Check for this and avoid | ||
984 | * walking through the entire list of ids which may be large. | ||
985 | */ | ||
986 | if (id == -1ULL) { | ||
987 | if (header->attrs > 0) | ||
988 | return &header->attr[0]->attr; | ||
989 | return NULL; | ||
990 | } | ||
991 | |||
992 | for (i = 0; i < header->attrs; i++) { | ||
993 | struct perf_header_attr *attr = header->attr[i]; | ||
994 | int j; | ||
995 | |||
996 | for (j = 0; j < attr->ids; j++) { | ||
997 | if (attr->id[j] == id) | ||
998 | return &attr->attr; | ||
999 | } | ||
1000 | } | ||
1001 | |||
1002 | return NULL; | ||
1003 | } | ||
1004 | |||
1005 | int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, | ||
1006 | event__handler_t process, | ||
1007 | struct perf_session *session) | ||
1008 | { | 916 | { |
1009 | event_t *ev; | 917 | union perf_event *ev; |
1010 | size_t size; | 918 | size_t size; |
1011 | int err; | 919 | int err; |
1012 | 920 | ||
@@ -1033,17 +941,15 @@ int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, | |||
1033 | return err; | 941 | return err; |
1034 | } | 942 | } |
1035 | 943 | ||
1036 | int event__synthesize_attrs(struct perf_header *self, event__handler_t process, | 944 | int perf_session__synthesize_attrs(struct perf_session *session, |
1037 | struct perf_session *session) | 945 | perf_event__handler_t process) |
1038 | { | 946 | { |
1039 | struct perf_header_attr *attr; | 947 | struct perf_evsel *attr; |
1040 | int i, err = 0; | 948 | int err = 0; |
1041 | |||
1042 | for (i = 0; i < self->attrs; i++) { | ||
1043 | attr = self->attr[i]; | ||
1044 | 949 | ||
1045 | err = event__synthesize_attr(&attr->attr, attr->ids, attr->id, | 950 | list_for_each_entry(attr, &session->evlist->entries, node) { |
1046 | process, session); | 951 | err = perf_event__synthesize_attr(&attr->attr, attr->ids, |
952 | attr->id, process, session); | ||
1047 | if (err) { | 953 | if (err) { |
1048 | pr_debug("failed to create perf header attribute\n"); | 954 | pr_debug("failed to create perf header attribute\n"); |
1049 | return err; | 955 | return err; |
@@ -1053,29 +959,39 @@ int event__synthesize_attrs(struct perf_header *self, event__handler_t process, | |||
1053 | return err; | 959 | return err; |
1054 | } | 960 | } |
1055 | 961 | ||
1056 | int event__process_attr(event_t *self, struct perf_session *session) | 962 | int perf_event__process_attr(union perf_event *event, |
963 | struct perf_session *session) | ||
1057 | { | 964 | { |
1058 | struct perf_header_attr *attr; | ||
1059 | unsigned int i, ids, n_ids; | 965 | unsigned int i, ids, n_ids; |
966 | struct perf_evsel *evsel; | ||
1060 | 967 | ||
1061 | attr = perf_header_attr__new(&self->attr.attr); | 968 | if (session->evlist == NULL) { |
1062 | if (attr == NULL) | 969 | session->evlist = perf_evlist__new(NULL, NULL); |
970 | if (session->evlist == NULL) | ||
971 | return -ENOMEM; | ||
972 | } | ||
973 | |||
974 | evsel = perf_evsel__new(&event->attr.attr, | ||
975 | session->evlist->nr_entries); | ||
976 | if (evsel == NULL) | ||
1063 | return -ENOMEM; | 977 | return -ENOMEM; |
1064 | 978 | ||
1065 | ids = self->header.size; | 979 | perf_evlist__add(session->evlist, evsel); |
1066 | ids -= (void *)&self->attr.id - (void *)self; | 980 | |
981 | ids = event->header.size; | ||
982 | ids -= (void *)&event->attr.id - (void *)event; | ||
1067 | n_ids = ids / sizeof(u64); | 983 | n_ids = ids / sizeof(u64); |
984 | /* | ||
985 | * We don't have the cpu and thread maps on the header, so | ||
986 | * for allocating the perf_sample_id table we fake 1 cpu and | ||
987 | * hattr->ids threads. | ||
988 | */ | ||
989 | if (perf_evsel__alloc_id(evsel, 1, n_ids)) | ||
990 | return -ENOMEM; | ||
1068 | 991 | ||
1069 | for (i = 0; i < n_ids; i++) { | 992 | for (i = 0; i < n_ids; i++) { |
1070 | if (perf_header_attr__add_id(attr, self->attr.id[i]) < 0) { | 993 | perf_evlist__id_add(session->evlist, evsel, 0, i, |
1071 | perf_header_attr__delete(attr); | 994 | event->attr.id[i]); |
1072 | return -ENOMEM; | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1076 | if (perf_header__add_attr(&session->header, attr) < 0) { | ||
1077 | perf_header_attr__delete(attr); | ||
1078 | return -ENOMEM; | ||
1079 | } | 995 | } |
1080 | 996 | ||
1081 | perf_session__update_sample_type(session); | 997 | perf_session__update_sample_type(session); |
@@ -1083,11 +999,11 @@ int event__process_attr(event_t *self, struct perf_session *session) | |||
1083 | return 0; | 999 | return 0; |
1084 | } | 1000 | } |
1085 | 1001 | ||
1086 | int event__synthesize_event_type(u64 event_id, char *name, | 1002 | int perf_event__synthesize_event_type(u64 event_id, char *name, |
1087 | event__handler_t process, | 1003 | perf_event__handler_t process, |
1088 | struct perf_session *session) | 1004 | struct perf_session *session) |
1089 | { | 1005 | { |
1090 | event_t ev; | 1006 | union perf_event ev; |
1091 | size_t size = 0; | 1007 | size_t size = 0; |
1092 | int err = 0; | 1008 | int err = 0; |
1093 | 1009 | ||
@@ -1108,8 +1024,8 @@ int event__synthesize_event_type(u64 event_id, char *name, | |||
1108 | return err; | 1024 | return err; |
1109 | } | 1025 | } |
1110 | 1026 | ||
1111 | int event__synthesize_event_types(event__handler_t process, | 1027 | int perf_event__synthesize_event_types(perf_event__handler_t process, |
1112 | struct perf_session *session) | 1028 | struct perf_session *session) |
1113 | { | 1029 | { |
1114 | struct perf_trace_event_type *type; | 1030 | struct perf_trace_event_type *type; |
1115 | int i, err = 0; | 1031 | int i, err = 0; |
@@ -1117,8 +1033,9 @@ int event__synthesize_event_types(event__handler_t process, | |||
1117 | for (i = 0; i < event_count; i++) { | 1033 | for (i = 0; i < event_count; i++) { |
1118 | type = &events[i]; | 1034 | type = &events[i]; |
1119 | 1035 | ||
1120 | err = event__synthesize_event_type(type->event_id, type->name, | 1036 | err = perf_event__synthesize_event_type(type->event_id, |
1121 | process, session); | 1037 | type->name, process, |
1038 | session); | ||
1122 | if (err) { | 1039 | if (err) { |
1123 | pr_debug("failed to create perf header event type\n"); | 1040 | pr_debug("failed to create perf header event type\n"); |
1124 | return err; | 1041 | return err; |
@@ -1128,28 +1045,28 @@ int event__synthesize_event_types(event__handler_t process, | |||
1128 | return err; | 1045 | return err; |
1129 | } | 1046 | } |
1130 | 1047 | ||
1131 | int event__process_event_type(event_t *self, | 1048 | int perf_event__process_event_type(union perf_event *event, |
1132 | struct perf_session *session __unused) | 1049 | struct perf_session *session __unused) |
1133 | { | 1050 | { |
1134 | if (perf_header__push_event(self->event_type.event_type.event_id, | 1051 | if (perf_header__push_event(event->event_type.event_type.event_id, |
1135 | self->event_type.event_type.name) < 0) | 1052 | event->event_type.event_type.name) < 0) |
1136 | return -ENOMEM; | 1053 | return -ENOMEM; |
1137 | 1054 | ||
1138 | return 0; | 1055 | return 0; |
1139 | } | 1056 | } |
1140 | 1057 | ||
1141 | int event__synthesize_tracing_data(int fd, struct list_head *pattrs, | 1058 | int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, |
1142 | event__handler_t process, | 1059 | perf_event__handler_t process, |
1143 | struct perf_session *session __unused) | 1060 | struct perf_session *session __unused) |
1144 | { | 1061 | { |
1145 | event_t ev; | 1062 | union perf_event ev; |
1146 | ssize_t size = 0, aligned_size = 0, padding; | 1063 | ssize_t size = 0, aligned_size = 0, padding; |
1147 | int err = 0; | 1064 | int err __used = 0; |
1148 | 1065 | ||
1149 | memset(&ev, 0, sizeof(ev)); | 1066 | memset(&ev, 0, sizeof(ev)); |
1150 | 1067 | ||
1151 | ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; | 1068 | ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; |
1152 | size = read_tracing_data_size(fd, pattrs); | 1069 | size = read_tracing_data_size(fd, &evlist->entries); |
1153 | if (size <= 0) | 1070 | if (size <= 0) |
1154 | return size; | 1071 | return size; |
1155 | aligned_size = ALIGN(size, sizeof(u64)); | 1072 | aligned_size = ALIGN(size, sizeof(u64)); |
@@ -1159,16 +1076,16 @@ int event__synthesize_tracing_data(int fd, struct list_head *pattrs, | |||
1159 | 1076 | ||
1160 | process(&ev, NULL, session); | 1077 | process(&ev, NULL, session); |
1161 | 1078 | ||
1162 | err = read_tracing_data(fd, pattrs); | 1079 | err = read_tracing_data(fd, &evlist->entries); |
1163 | write_padded(fd, NULL, 0, padding); | 1080 | write_padded(fd, NULL, 0, padding); |
1164 | 1081 | ||
1165 | return aligned_size; | 1082 | return aligned_size; |
1166 | } | 1083 | } |
1167 | 1084 | ||
1168 | int event__process_tracing_data(event_t *self, | 1085 | int perf_event__process_tracing_data(union perf_event *event, |
1169 | struct perf_session *session) | 1086 | struct perf_session *session) |
1170 | { | 1087 | { |
1171 | ssize_t size_read, padding, size = self->tracing_data.size; | 1088 | ssize_t size_read, padding, size = event->tracing_data.size; |
1172 | off_t offset = lseek(session->fd, 0, SEEK_CUR); | 1089 | off_t offset = lseek(session->fd, 0, SEEK_CUR); |
1173 | char buf[BUFSIZ]; | 1090 | char buf[BUFSIZ]; |
1174 | 1091 | ||
@@ -1194,12 +1111,12 @@ int event__process_tracing_data(event_t *self, | |||
1194 | return size_read + padding; | 1111 | return size_read + padding; |
1195 | } | 1112 | } |
1196 | 1113 | ||
1197 | int event__synthesize_build_id(struct dso *pos, u16 misc, | 1114 | int perf_event__synthesize_build_id(struct dso *pos, u16 misc, |
1198 | event__handler_t process, | 1115 | perf_event__handler_t process, |
1199 | struct machine *machine, | 1116 | struct machine *machine, |
1200 | struct perf_session *session) | 1117 | struct perf_session *session) |
1201 | { | 1118 | { |
1202 | event_t ev; | 1119 | union perf_event ev; |
1203 | size_t len; | 1120 | size_t len; |
1204 | int err = 0; | 1121 | int err = 0; |
1205 | 1122 | ||
@@ -1222,11 +1139,11 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, | |||
1222 | return err; | 1139 | return err; |
1223 | } | 1140 | } |
1224 | 1141 | ||
1225 | int event__process_build_id(event_t *self, | 1142 | int perf_event__process_build_id(union perf_event *event, |
1226 | struct perf_session *session) | 1143 | struct perf_session *session) |
1227 | { | 1144 | { |
1228 | __event_process_build_id(&self->build_id, | 1145 | __event_process_build_id(&event->build_id, |
1229 | self->build_id.filename, | 1146 | event->build_id.filename, |
1230 | session); | 1147 | session); |
1231 | return 0; | 1148 | return 0; |
1232 | } | 1149 | } |