diff options
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 546 |
1 files changed, 234 insertions, 312 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index f6a929e74981..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 | ||
@@ -270,11 +189,15 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, | |||
270 | const char *name, bool is_kallsyms) | 189 | const char *name, bool is_kallsyms) |
271 | { | 190 | { |
272 | const size_t size = PATH_MAX; | 191 | const size_t size = PATH_MAX; |
273 | char *realname = realpath(name, NULL), | 192 | char *realname, *filename = malloc(size), |
274 | *filename = malloc(size), | ||
275 | *linkname = malloc(size), *targetname; | 193 | *linkname = malloc(size), *targetname; |
276 | int len, err = -1; | 194 | int len, err = -1; |
277 | 195 | ||
196 | if (is_kallsyms) | ||
197 | realname = (char *)name; | ||
198 | else | ||
199 | realname = realpath(name, NULL); | ||
200 | |||
278 | if (realname == NULL || filename == NULL || linkname == NULL) | 201 | if (realname == NULL || filename == NULL || linkname == NULL) |
279 | goto out_free; | 202 | goto out_free; |
280 | 203 | ||
@@ -306,7 +229,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, | |||
306 | if (symlink(targetname, linkname) == 0) | 229 | if (symlink(targetname, linkname) == 0) |
307 | err = 0; | 230 | err = 0; |
308 | out_free: | 231 | out_free: |
309 | free(realname); | 232 | if (!is_kallsyms) |
233 | free(realname); | ||
310 | free(filename); | 234 | free(filename); |
311 | free(linkname); | 235 | free(linkname); |
312 | return err; | 236 | return err; |
@@ -361,12 +285,12 @@ out_free: | |||
361 | return err; | 285 | return err; |
362 | } | 286 | } |
363 | 287 | ||
364 | 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) |
365 | { | 289 | { |
366 | bool is_kallsyms = self->kernel && self->long_name[0] != '/'; | 290 | bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; |
367 | 291 | ||
368 | 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), |
369 | self->long_name, debugdir, is_kallsyms); | 293 | dso->long_name, debugdir, is_kallsyms); |
370 | } | 294 | } |
371 | 295 | ||
372 | 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) |
@@ -381,14 +305,14 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) | |||
381 | return err; | 305 | return err; |
382 | } | 306 | } |
383 | 307 | ||
384 | 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) |
385 | { | 309 | { |
386 | int ret = __dsos__cache_build_ids(&self->kernel_dsos, debugdir); | 310 | int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir); |
387 | ret |= __dsos__cache_build_ids(&self->user_dsos, debugdir); | 311 | ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir); |
388 | return ret; | 312 | return ret; |
389 | } | 313 | } |
390 | 314 | ||
391 | static int perf_session__cache_build_ids(struct perf_session *self) | 315 | static int perf_session__cache_build_ids(struct perf_session *session) |
392 | { | 316 | { |
393 | struct rb_node *nd; | 317 | struct rb_node *nd; |
394 | int ret; | 318 | int ret; |
@@ -399,28 +323,28 @@ static int perf_session__cache_build_ids(struct perf_session *self) | |||
399 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) | 323 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) |
400 | return -1; | 324 | return -1; |
401 | 325 | ||
402 | ret = machine__cache_build_ids(&self->host_machine, debugdir); | 326 | ret = machine__cache_build_ids(&session->host_machine, debugdir); |
403 | 327 | ||
404 | for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) { | 328 | for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { |
405 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | 329 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
406 | ret |= machine__cache_build_ids(pos, debugdir); | 330 | ret |= machine__cache_build_ids(pos, debugdir); |
407 | } | 331 | } |
408 | return ret ? -1 : 0; | 332 | return ret ? -1 : 0; |
409 | } | 333 | } |
410 | 334 | ||
411 | 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) |
412 | { | 336 | { |
413 | bool ret = __dsos__read_build_ids(&self->kernel_dsos, with_hits); | 337 | bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits); |
414 | ret |= __dsos__read_build_ids(&self->user_dsos, with_hits); | 338 | ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits); |
415 | return ret; | 339 | return ret; |
416 | } | 340 | } |
417 | 341 | ||
418 | 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) |
419 | { | 343 | { |
420 | struct rb_node *nd; | 344 | struct rb_node *nd; |
421 | bool ret = machine__read_build_ids(&self->host_machine, with_hits); | 345 | bool ret = machine__read_build_ids(&session->host_machine, with_hits); |
422 | 346 | ||
423 | for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) { | 347 | for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { |
424 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | 348 | struct machine *pos = rb_entry(nd, struct machine, rb_node); |
425 | ret |= machine__read_build_ids(pos, with_hits); | 349 | ret |= machine__read_build_ids(pos, with_hits); |
426 | } | 350 | } |
@@ -428,7 +352,8 @@ static bool perf_session__read_build_ids(struct perf_session *self, bool with_hi | |||
428 | return ret; | 352 | return ret; |
429 | } | 353 | } |
430 | 354 | ||
431 | 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) | ||
432 | { | 357 | { |
433 | int nr_sections; | 358 | int nr_sections; |
434 | struct perf_session *session; | 359 | struct perf_session *session; |
@@ -437,13 +362,13 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
437 | u64 sec_start; | 362 | u64 sec_start; |
438 | int idx = 0, err; | 363 | int idx = 0, err; |
439 | 364 | ||
440 | session = container_of(self, struct perf_session, header); | 365 | session = container_of(header, struct perf_session, header); |
441 | 366 | ||
442 | if (perf_header__has_feat(self, HEADER_BUILD_ID && | 367 | if (perf_header__has_feat(header, HEADER_BUILD_ID && |
443 | !perf_session__read_build_ids(session, true))) | 368 | !perf_session__read_build_ids(session, true))) |
444 | perf_header__clear_feat(self, HEADER_BUILD_ID); | 369 | perf_header__clear_feat(header, HEADER_BUILD_ID); |
445 | 370 | ||
446 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | 371 | nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); |
447 | if (!nr_sections) | 372 | if (!nr_sections) |
448 | return 0; | 373 | return 0; |
449 | 374 | ||
@@ -453,28 +378,28 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
453 | 378 | ||
454 | sec_size = sizeof(*feat_sec) * nr_sections; | 379 | sec_size = sizeof(*feat_sec) * nr_sections; |
455 | 380 | ||
456 | sec_start = self->data_offset + self->data_size; | 381 | sec_start = header->data_offset + header->data_size; |
457 | lseek(fd, sec_start + sec_size, SEEK_SET); | 382 | lseek(fd, sec_start + sec_size, SEEK_SET); |
458 | 383 | ||
459 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { | 384 | if (perf_header__has_feat(header, HEADER_TRACE_INFO)) { |
460 | struct perf_file_section *trace_sec; | 385 | struct perf_file_section *trace_sec; |
461 | 386 | ||
462 | trace_sec = &feat_sec[idx++]; | 387 | trace_sec = &feat_sec[idx++]; |
463 | 388 | ||
464 | /* Write trace info */ | 389 | /* Write trace info */ |
465 | trace_sec->offset = lseek(fd, 0, SEEK_CUR); | 390 | trace_sec->offset = lseek(fd, 0, SEEK_CUR); |
466 | read_tracing_data(fd, &evsel_list); | 391 | read_tracing_data(fd, &evlist->entries); |
467 | trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; | 392 | trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; |
468 | } | 393 | } |
469 | 394 | ||
470 | if (perf_header__has_feat(self, HEADER_BUILD_ID)) { | 395 | if (perf_header__has_feat(header, HEADER_BUILD_ID)) { |
471 | struct perf_file_section *buildid_sec; | 396 | struct perf_file_section *buildid_sec; |
472 | 397 | ||
473 | buildid_sec = &feat_sec[idx++]; | 398 | buildid_sec = &feat_sec[idx++]; |
474 | 399 | ||
475 | /* Write build-ids */ | 400 | /* Write build-ids */ |
476 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); | 401 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); |
477 | err = dsos__write_buildid_table(self, fd); | 402 | err = dsos__write_buildid_table(header, fd); |
478 | if (err < 0) { | 403 | if (err < 0) { |
479 | pr_debug("failed to write buildid table\n"); | 404 | pr_debug("failed to write buildid table\n"); |
480 | goto out_free; | 405 | goto out_free; |
@@ -513,32 +438,41 @@ int perf_header__write_pipe(int fd) | |||
513 | return 0; | 438 | return 0; |
514 | } | 439 | } |
515 | 440 | ||
516 | 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) | ||
517 | { | 444 | { |
518 | struct perf_file_header f_header; | 445 | struct perf_file_header f_header; |
519 | struct perf_file_attr f_attr; | 446 | struct perf_file_attr f_attr; |
520 | struct perf_header_attr *attr; | 447 | struct perf_header *header = &session->header; |
521 | int i, err; | 448 | struct perf_evsel *attr, *pair = NULL; |
449 | int err; | ||
522 | 450 | ||
523 | lseek(fd, sizeof(f_header), SEEK_SET); | 451 | lseek(fd, sizeof(f_header), SEEK_SET); |
524 | 452 | ||
525 | for (i = 0; i < self->attrs; i++) { | 453 | if (session->evlist != evlist) |
526 | attr = self->attr[i]; | 454 | pair = list_entry(session->evlist->entries.next, struct perf_evsel, node); |
527 | 455 | ||
456 | list_for_each_entry(attr, &evlist->entries, node) { | ||
528 | attr->id_offset = lseek(fd, 0, SEEK_CUR); | 457 | attr->id_offset = lseek(fd, 0, SEEK_CUR); |
529 | err = do_write(fd, attr->id, attr->ids * sizeof(u64)); | 458 | err = do_write(fd, attr->id, attr->ids * sizeof(u64)); |
530 | if (err < 0) { | 459 | if (err < 0) { |
460 | out_err_write: | ||
531 | pr_debug("failed to write perf header\n"); | 461 | pr_debug("failed to write perf header\n"); |
532 | return err; | 462 | return err; |
533 | } | 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 | } | ||
534 | } | 471 | } |
535 | 472 | ||
473 | header->attr_offset = lseek(fd, 0, SEEK_CUR); | ||
536 | 474 | ||
537 | self->attr_offset = lseek(fd, 0, SEEK_CUR); | 475 | list_for_each_entry(attr, &evlist->entries, node) { |
538 | |||
539 | for (i = 0; i < self->attrs; i++) { | ||
540 | attr = self->attr[i]; | ||
541 | |||
542 | f_attr = (struct perf_file_attr){ | 476 | f_attr = (struct perf_file_attr){ |
543 | .attr = attr->attr, | 477 | .attr = attr->attr, |
544 | .ids = { | 478 | .ids = { |
@@ -553,20 +487,20 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
553 | } | 487 | } |
554 | } | 488 | } |
555 | 489 | ||
556 | self->event_offset = lseek(fd, 0, SEEK_CUR); | 490 | header->event_offset = lseek(fd, 0, SEEK_CUR); |
557 | self->event_size = event_count * sizeof(struct perf_trace_event_type); | 491 | header->event_size = event_count * sizeof(struct perf_trace_event_type); |
558 | if (events) { | 492 | if (events) { |
559 | err = do_write(fd, events, self->event_size); | 493 | err = do_write(fd, events, header->event_size); |
560 | if (err < 0) { | 494 | if (err < 0) { |
561 | pr_debug("failed to write perf header events\n"); | 495 | pr_debug("failed to write perf header events\n"); |
562 | return err; | 496 | return err; |
563 | } | 497 | } |
564 | } | 498 | } |
565 | 499 | ||
566 | self->data_offset = lseek(fd, 0, SEEK_CUR); | 500 | header->data_offset = lseek(fd, 0, SEEK_CUR); |
567 | 501 | ||
568 | if (at_exit) { | 502 | if (at_exit) { |
569 | err = perf_header__adds_write(self, fd); | 503 | err = perf_header__adds_write(header, evlist, fd); |
570 | if (err < 0) | 504 | if (err < 0) |
571 | return err; | 505 | return err; |
572 | } | 506 | } |
@@ -576,20 +510,20 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
576 | .size = sizeof(f_header), | 510 | .size = sizeof(f_header), |
577 | .attr_size = sizeof(f_attr), | 511 | .attr_size = sizeof(f_attr), |
578 | .attrs = { | 512 | .attrs = { |
579 | .offset = self->attr_offset, | 513 | .offset = header->attr_offset, |
580 | .size = self->attrs * sizeof(f_attr), | 514 | .size = evlist->nr_entries * sizeof(f_attr), |
581 | }, | 515 | }, |
582 | .data = { | 516 | .data = { |
583 | .offset = self->data_offset, | 517 | .offset = header->data_offset, |
584 | .size = self->data_size, | 518 | .size = header->data_size, |
585 | }, | 519 | }, |
586 | .event_types = { | 520 | .event_types = { |
587 | .offset = self->event_offset, | 521 | .offset = header->event_offset, |
588 | .size = self->event_size, | 522 | .size = header->event_size, |
589 | }, | 523 | }, |
590 | }; | 524 | }; |
591 | 525 | ||
592 | 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)); |
593 | 527 | ||
594 | lseek(fd, 0, SEEK_SET); | 528 | lseek(fd, 0, SEEK_SET); |
595 | err = do_write(fd, &f_header, sizeof(f_header)); | 529 | err = do_write(fd, &f_header, sizeof(f_header)); |
@@ -597,26 +531,26 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
597 | pr_debug("failed to write perf header\n"); | 531 | pr_debug("failed to write perf header\n"); |
598 | return err; | 532 | return err; |
599 | } | 533 | } |
600 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | 534 | lseek(fd, header->data_offset + header->data_size, SEEK_SET); |
601 | 535 | ||
602 | self->frozen = 1; | 536 | header->frozen = 1; |
603 | return 0; | 537 | return 0; |
604 | } | 538 | } |
605 | 539 | ||
606 | static int perf_header__getbuffer64(struct perf_header *self, | 540 | static int perf_header__getbuffer64(struct perf_header *header, |
607 | int fd, void *buf, size_t size) | 541 | int fd, void *buf, size_t size) |
608 | { | 542 | { |
609 | if (readn(fd, buf, size) <= 0) | 543 | if (readn(fd, buf, size) <= 0) |
610 | return -1; | 544 | return -1; |
611 | 545 | ||
612 | if (self->needs_swap) | 546 | if (header->needs_swap) |
613 | mem_bswap_64(buf, size); | 547 | mem_bswap_64(buf, size); |
614 | 548 | ||
615 | return 0; | 549 | return 0; |
616 | } | 550 | } |
617 | 551 | ||
618 | int perf_header__process_sections(struct perf_header *self, int fd, | 552 | int perf_header__process_sections(struct perf_header *header, int fd, |
619 | int (*process)(struct perf_file_section *self, | 553 | int (*process)(struct perf_file_section *section, |
620 | struct perf_header *ph, | 554 | struct perf_header *ph, |
621 | int feat, int fd)) | 555 | int feat, int fd)) |
622 | { | 556 | { |
@@ -626,7 +560,7 @@ int perf_header__process_sections(struct perf_header *self, int fd, | |||
626 | int idx = 0; | 560 | int idx = 0; |
627 | int err = -1, feat = 1; | 561 | int err = -1, feat = 1; |
628 | 562 | ||
629 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | 563 | nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); |
630 | if (!nr_sections) | 564 | if (!nr_sections) |
631 | return 0; | 565 | return 0; |
632 | 566 | ||
@@ -636,17 +570,17 @@ int perf_header__process_sections(struct perf_header *self, int fd, | |||
636 | 570 | ||
637 | sec_size = sizeof(*feat_sec) * nr_sections; | 571 | sec_size = sizeof(*feat_sec) * nr_sections; |
638 | 572 | ||
639 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | 573 | lseek(fd, header->data_offset + header->data_size, SEEK_SET); |
640 | 574 | ||
641 | if (perf_header__getbuffer64(self, fd, feat_sec, sec_size)) | 575 | if (perf_header__getbuffer64(header, fd, feat_sec, sec_size)) |
642 | goto out_free; | 576 | goto out_free; |
643 | 577 | ||
644 | err = 0; | 578 | err = 0; |
645 | while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { | 579 | while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { |
646 | if (perf_header__has_feat(self, feat)) { | 580 | if (perf_header__has_feat(header, feat)) { |
647 | struct perf_file_section *sec = &feat_sec[idx++]; | 581 | struct perf_file_section *sec = &feat_sec[idx++]; |
648 | 582 | ||
649 | err = process(sec, self, feat, fd); | 583 | err = process(sec, header, feat, fd); |
650 | if (err < 0) | 584 | if (err < 0) |
651 | break; | 585 | break; |
652 | } | 586 | } |
@@ -657,35 +591,35 @@ out_free: | |||
657 | return err; | 591 | return err; |
658 | } | 592 | } |
659 | 593 | ||
660 | int perf_file_header__read(struct perf_file_header *self, | 594 | int perf_file_header__read(struct perf_file_header *header, |
661 | struct perf_header *ph, int fd) | 595 | struct perf_header *ph, int fd) |
662 | { | 596 | { |
663 | lseek(fd, 0, SEEK_SET); | 597 | lseek(fd, 0, SEEK_SET); |
664 | 598 | ||
665 | if (readn(fd, self, sizeof(*self)) <= 0 || | 599 | if (readn(fd, header, sizeof(*header)) <= 0 || |
666 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | 600 | memcmp(&header->magic, __perf_magic, sizeof(header->magic))) |
667 | return -1; | 601 | return -1; |
668 | 602 | ||
669 | if (self->attr_size != sizeof(struct perf_file_attr)) { | 603 | if (header->attr_size != sizeof(struct perf_file_attr)) { |
670 | u64 attr_size = bswap_64(self->attr_size); | 604 | u64 attr_size = bswap_64(header->attr_size); |
671 | 605 | ||
672 | if (attr_size != sizeof(struct perf_file_attr)) | 606 | if (attr_size != sizeof(struct perf_file_attr)) |
673 | return -1; | 607 | return -1; |
674 | 608 | ||
675 | mem_bswap_64(self, offsetof(struct perf_file_header, | 609 | mem_bswap_64(header, offsetof(struct perf_file_header, |
676 | adds_features)); | 610 | adds_features)); |
677 | ph->needs_swap = true; | 611 | ph->needs_swap = true; |
678 | } | 612 | } |
679 | 613 | ||
680 | if (self->size != sizeof(*self)) { | 614 | if (header->size != sizeof(*header)) { |
681 | /* Support the previous format */ | 615 | /* Support the previous format */ |
682 | if (self->size == offsetof(typeof(*self), adds_features)) | 616 | if (header->size == offsetof(typeof(*header), adds_features)) |
683 | bitmap_zero(self->adds_features, HEADER_FEAT_BITS); | 617 | bitmap_zero(header->adds_features, HEADER_FEAT_BITS); |
684 | else | 618 | else |
685 | return -1; | 619 | return -1; |
686 | } | 620 | } |
687 | 621 | ||
688 | memcpy(&ph->adds_features, &self->adds_features, | 622 | memcpy(&ph->adds_features, &header->adds_features, |
689 | sizeof(ph->adds_features)); | 623 | sizeof(ph->adds_features)); |
690 | /* | 624 | /* |
691 | * 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 |
@@ -699,10 +633,10 @@ int perf_file_header__read(struct perf_file_header *self, | |||
699 | perf_header__set_feat(ph, HEADER_BUILD_ID); | 633 | perf_header__set_feat(ph, HEADER_BUILD_ID); |
700 | } | 634 | } |
701 | 635 | ||
702 | ph->event_offset = self->event_types.offset; | 636 | ph->event_offset = header->event_types.offset; |
703 | ph->event_size = self->event_types.size; | 637 | ph->event_size = header->event_types.size; |
704 | ph->data_offset = self->data.offset; | 638 | ph->data_offset = header->data.offset; |
705 | ph->data_size = self->data.size; | 639 | ph->data_size = header->data.size; |
706 | return 0; | 640 | return 0; |
707 | } | 641 | } |
708 | 642 | ||
@@ -761,11 +695,10 @@ out: | |||
761 | return err; | 695 | return err; |
762 | } | 696 | } |
763 | 697 | ||
764 | static int perf_header__read_build_ids(struct perf_header *self, | 698 | static int perf_header__read_build_ids(struct perf_header *header, |
765 | int input, u64 offset, u64 size) | 699 | int input, u64 offset, u64 size) |
766 | { | 700 | { |
767 | struct perf_session *session = container_of(self, | 701 | struct perf_session *session = container_of(header, struct perf_session, header); |
768 | struct perf_session, header); | ||
769 | struct build_id_event bev; | 702 | struct build_id_event bev; |
770 | char filename[PATH_MAX]; | 703 | char filename[PATH_MAX]; |
771 | u64 limit = offset + size; | 704 | u64 limit = offset + size; |
@@ -777,7 +710,7 @@ static int perf_header__read_build_ids(struct perf_header *self, | |||
777 | if (read(input, &bev, sizeof(bev)) != sizeof(bev)) | 710 | if (read(input, &bev, sizeof(bev)) != sizeof(bev)) |
778 | goto out; | 711 | goto out; |
779 | 712 | ||
780 | if (self->needs_swap) | 713 | if (header->needs_swap) |
781 | perf_event_header__bswap(&bev.header); | 714 | perf_event_header__bswap(&bev.header); |
782 | 715 | ||
783 | len = bev.header.size - sizeof(bev); | 716 | len = bev.header.size - sizeof(bev); |
@@ -793,13 +726,13 @@ out: | |||
793 | return err; | 726 | return err; |
794 | } | 727 | } |
795 | 728 | ||
796 | static int perf_file_section__process(struct perf_file_section *self, | 729 | static int perf_file_section__process(struct perf_file_section *section, |
797 | struct perf_header *ph, | 730 | struct perf_header *ph, |
798 | int feat, int fd) | 731 | int feat, int fd) |
799 | { | 732 | { |
800 | if (lseek(fd, self->offset, SEEK_SET) == (off_t)-1) { | 733 | if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) { |
801 | pr_debug("Failed to lseek to %" PRIu64 " offset for feature " | 734 | pr_debug("Failed to lseek to %" PRIu64 " offset for feature " |
802 | "%d, continuing...\n", self->offset, feat); | 735 | "%d, continuing...\n", section->offset, feat); |
803 | return 0; | 736 | return 0; |
804 | } | 737 | } |
805 | 738 | ||
@@ -809,7 +742,7 @@ static int perf_file_section__process(struct perf_file_section *self, | |||
809 | break; | 742 | break; |
810 | 743 | ||
811 | case HEADER_BUILD_ID: | 744 | case HEADER_BUILD_ID: |
812 | 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)) |
813 | pr_debug("Failed to read buildids, continuing...\n"); | 746 | pr_debug("Failed to read buildids, continuing...\n"); |
814 | break; | 747 | break; |
815 | default: | 748 | default: |
@@ -819,21 +752,21 @@ static int perf_file_section__process(struct perf_file_section *self, | |||
819 | return 0; | 752 | return 0; |
820 | } | 753 | } |
821 | 754 | ||
822 | 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, |
823 | struct perf_header *ph, int fd, | 756 | struct perf_header *ph, int fd, |
824 | bool repipe) | 757 | bool repipe) |
825 | { | 758 | { |
826 | if (readn(fd, self, sizeof(*self)) <= 0 || | 759 | if (readn(fd, header, sizeof(*header)) <= 0 || |
827 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | 760 | memcmp(&header->magic, __perf_magic, sizeof(header->magic))) |
828 | return -1; | 761 | return -1; |
829 | 762 | ||
830 | if (repipe && do_write(STDOUT_FILENO, self, sizeof(*self)) < 0) | 763 | if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0) |
831 | return -1; | 764 | return -1; |
832 | 765 | ||
833 | if (self->size != sizeof(*self)) { | 766 | if (header->size != sizeof(*header)) { |
834 | u64 size = bswap_64(self->size); | 767 | u64 size = bswap_64(header->size); |
835 | 768 | ||
836 | if (size != sizeof(*self)) | 769 | if (size != sizeof(*header)) |
837 | return -1; | 770 | return -1; |
838 | 771 | ||
839 | ph->needs_swap = true; | 772 | ph->needs_swap = true; |
@@ -844,10 +777,10 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, | |||
844 | 777 | ||
845 | 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) |
846 | { | 779 | { |
847 | struct perf_header *self = &session->header; | 780 | struct perf_header *header = &session->header; |
848 | struct perf_pipe_file_header f_header; | 781 | struct perf_pipe_file_header f_header; |
849 | 782 | ||
850 | if (perf_file_header__read_pipe(&f_header, self, fd, | 783 | if (perf_file_header__read_pipe(&f_header, header, fd, |
851 | session->repipe) < 0) { | 784 | session->repipe) < 0) { |
852 | pr_debug("incompatible file format\n"); | 785 | pr_debug("incompatible file format\n"); |
853 | return -EINVAL; | 786 | return -EINVAL; |
@@ -858,18 +791,22 @@ static int perf_header__read_pipe(struct perf_session *session, int fd) | |||
858 | return 0; | 791 | return 0; |
859 | } | 792 | } |
860 | 793 | ||
861 | int perf_header__read(struct perf_session *session, int fd) | 794 | int perf_session__read_header(struct perf_session *session, int fd) |
862 | { | 795 | { |
863 | struct perf_header *self = &session->header; | 796 | struct perf_header *header = &session->header; |
864 | struct perf_file_header f_header; | 797 | struct perf_file_header f_header; |
865 | struct perf_file_attr f_attr; | 798 | struct perf_file_attr f_attr; |
866 | u64 f_id; | 799 | u64 f_id; |
867 | int nr_attrs, nr_ids, i, j; | 800 | int nr_attrs, nr_ids, i, j; |
868 | 801 | ||
802 | session->evlist = perf_evlist__new(NULL, NULL); | ||
803 | if (session->evlist == NULL) | ||
804 | return -ENOMEM; | ||
805 | |||
869 | if (session->fd_pipe) | 806 | if (session->fd_pipe) |
870 | return perf_header__read_pipe(session, fd); | 807 | return perf_header__read_pipe(session, fd); |
871 | 808 | ||
872 | if (perf_file_header__read(&f_header, self, fd) < 0) { | 809 | if (perf_file_header__read(&f_header, header, fd) < 0) { |
873 | pr_debug("incompatible file format\n"); | 810 | pr_debug("incompatible file format\n"); |
874 | return -EINVAL; | 811 | return -EINVAL; |
875 | } | 812 | } |
@@ -878,33 +815,39 @@ int perf_header__read(struct perf_session *session, int fd) | |||
878 | lseek(fd, f_header.attrs.offset, SEEK_SET); | 815 | lseek(fd, f_header.attrs.offset, SEEK_SET); |
879 | 816 | ||
880 | for (i = 0; i < nr_attrs; i++) { | 817 | for (i = 0; i < nr_attrs; i++) { |
881 | struct perf_header_attr *attr; | 818 | struct perf_evsel *evsel; |
882 | off_t tmp; | 819 | off_t tmp; |
883 | 820 | ||
884 | if (perf_header__getbuffer64(self, fd, &f_attr, sizeof(f_attr))) | 821 | if (perf_header__getbuffer64(header, fd, &f_attr, sizeof(f_attr))) |
885 | goto out_errno; | 822 | goto out_errno; |
886 | 823 | ||
887 | tmp = lseek(fd, 0, SEEK_CUR); | 824 | tmp = lseek(fd, 0, SEEK_CUR); |
825 | evsel = perf_evsel__new(&f_attr.attr, i); | ||
888 | 826 | ||
889 | attr = perf_header_attr__new(&f_attr.attr); | 827 | if (evsel == NULL) |
890 | if (attr == NULL) | 828 | goto out_delete_evlist; |
891 | 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); | ||
892 | 834 | ||
893 | 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 | |||
894 | lseek(fd, f_attr.ids.offset, SEEK_SET); | 844 | lseek(fd, f_attr.ids.offset, SEEK_SET); |
895 | 845 | ||
896 | for (j = 0; j < nr_ids; j++) { | 846 | for (j = 0; j < nr_ids; j++) { |
897 | if (perf_header__getbuffer64(self, fd, &f_id, sizeof(f_id))) | 847 | if (perf_header__getbuffer64(header, fd, &f_id, sizeof(f_id))) |
898 | goto out_errno; | 848 | goto out_errno; |
899 | 849 | ||
900 | if (perf_header_attr__add_id(attr, f_id) < 0) { | 850 | perf_evlist__id_add(session->evlist, evsel, 0, j, f_id); |
901 | perf_header_attr__delete(attr); | ||
902 | return -ENOMEM; | ||
903 | } | ||
904 | } | ||
905 | if (perf_header__add_attr(self, attr) < 0) { | ||
906 | perf_header_attr__delete(attr); | ||
907 | return -ENOMEM; | ||
908 | } | 851 | } |
909 | 852 | ||
910 | lseek(fd, tmp, SEEK_SET); | 853 | lseek(fd, tmp, SEEK_SET); |
@@ -915,93 +858,63 @@ int perf_header__read(struct perf_session *session, int fd) | |||
915 | events = malloc(f_header.event_types.size); | 858 | events = malloc(f_header.event_types.size); |
916 | if (events == NULL) | 859 | if (events == NULL) |
917 | return -ENOMEM; | 860 | return -ENOMEM; |
918 | if (perf_header__getbuffer64(self, fd, events, | 861 | if (perf_header__getbuffer64(header, fd, events, |
919 | f_header.event_types.size)) | 862 | f_header.event_types.size)) |
920 | goto out_errno; | 863 | goto out_errno; |
921 | 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); |
922 | } | 865 | } |
923 | 866 | ||
924 | perf_header__process_sections(self, fd, perf_file_section__process); | 867 | perf_header__process_sections(header, fd, perf_file_section__process); |
925 | 868 | ||
926 | lseek(fd, self->data_offset, SEEK_SET); | 869 | lseek(fd, header->data_offset, SEEK_SET); |
927 | 870 | ||
928 | self->frozen = 1; | 871 | header->frozen = 1; |
929 | return 0; | 872 | return 0; |
930 | out_errno: | 873 | out_errno: |
931 | return -errno; | 874 | return -errno; |
875 | |||
876 | out_delete_evlist: | ||
877 | perf_evlist__delete(session->evlist); | ||
878 | session->evlist = NULL; | ||
879 | return -ENOMEM; | ||
932 | } | 880 | } |
933 | 881 | ||
934 | u64 perf_header__sample_type(struct perf_header *header) | 882 | u64 perf_evlist__sample_type(struct perf_evlist *evlist) |
935 | { | 883 | { |
884 | struct perf_evsel *pos; | ||
936 | u64 type = 0; | 885 | u64 type = 0; |
937 | int i; | ||
938 | |||
939 | for (i = 0; i < header->attrs; i++) { | ||
940 | struct perf_header_attr *attr = header->attr[i]; | ||
941 | 886 | ||
887 | list_for_each_entry(pos, &evlist->entries, node) { | ||
942 | if (!type) | 888 | if (!type) |
943 | type = attr->attr.sample_type; | 889 | type = pos->attr.sample_type; |
944 | else if (type != attr->attr.sample_type) | 890 | else if (type != pos->attr.sample_type) |
945 | die("non matching sample_type"); | 891 | die("non matching sample_type"); |
946 | } | 892 | } |
947 | 893 | ||
948 | return type; | 894 | return type; |
949 | } | 895 | } |
950 | 896 | ||
951 | bool perf_header__sample_id_all(const struct perf_header *header) | 897 | bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) |
952 | { | 898 | { |
953 | bool value = false, first = true; | 899 | bool value = false, first = true; |
954 | int i; | 900 | struct perf_evsel *pos; |
955 | |||
956 | for (i = 0; i < header->attrs; i++) { | ||
957 | struct perf_header_attr *attr = header->attr[i]; | ||
958 | 901 | ||
902 | list_for_each_entry(pos, &evlist->entries, node) { | ||
959 | if (first) { | 903 | if (first) { |
960 | value = attr->attr.sample_id_all; | 904 | value = pos->attr.sample_id_all; |
961 | first = false; | 905 | first = false; |
962 | } else if (value != attr->attr.sample_id_all) | 906 | } else if (value != pos->attr.sample_id_all) |
963 | die("non matching sample_id_all"); | 907 | die("non matching sample_id_all"); |
964 | } | 908 | } |
965 | 909 | ||
966 | return value; | 910 | return value; |
967 | } | 911 | } |
968 | 912 | ||
969 | struct perf_event_attr * | 913 | int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, |
970 | perf_header__find_attr(u64 id, struct perf_header *header) | 914 | perf_event__handler_t process, |
971 | { | 915 | struct perf_session *session) |
972 | int i; | ||
973 | |||
974 | /* | ||
975 | * We set id to -1 if the data file doesn't contain sample | ||
976 | * ids. This can happen when the data file contains one type | ||
977 | * of event and in that case, the header can still store the | ||
978 | * event attribute information. Check for this and avoid | ||
979 | * walking through the entire list of ids which may be large. | ||
980 | */ | ||
981 | if (id == -1ULL) { | ||
982 | if (header->attrs > 0) | ||
983 | return &header->attr[0]->attr; | ||
984 | return NULL; | ||
985 | } | ||
986 | |||
987 | for (i = 0; i < header->attrs; i++) { | ||
988 | struct perf_header_attr *attr = header->attr[i]; | ||
989 | int j; | ||
990 | |||
991 | for (j = 0; j < attr->ids; j++) { | ||
992 | if (attr->id[j] == id) | ||
993 | return &attr->attr; | ||
994 | } | ||
995 | } | ||
996 | |||
997 | return NULL; | ||
998 | } | ||
999 | |||
1000 | int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, | ||
1001 | event__handler_t process, | ||
1002 | struct perf_session *session) | ||
1003 | { | 916 | { |
1004 | event_t *ev; | 917 | union perf_event *ev; |
1005 | size_t size; | 918 | size_t size; |
1006 | int err; | 919 | int err; |
1007 | 920 | ||
@@ -1028,17 +941,15 @@ int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, | |||
1028 | return err; | 941 | return err; |
1029 | } | 942 | } |
1030 | 943 | ||
1031 | int event__synthesize_attrs(struct perf_header *self, event__handler_t process, | 944 | int perf_session__synthesize_attrs(struct perf_session *session, |
1032 | struct perf_session *session) | 945 | perf_event__handler_t process) |
1033 | { | 946 | { |
1034 | struct perf_header_attr *attr; | 947 | struct perf_evsel *attr; |
1035 | int i, err = 0; | 948 | int err = 0; |
1036 | |||
1037 | for (i = 0; i < self->attrs; i++) { | ||
1038 | attr = self->attr[i]; | ||
1039 | 949 | ||
1040 | err = event__synthesize_attr(&attr->attr, attr->ids, attr->id, | 950 | list_for_each_entry(attr, &session->evlist->entries, node) { |
1041 | process, session); | 951 | err = perf_event__synthesize_attr(&attr->attr, attr->ids, |
952 | attr->id, process, session); | ||
1042 | if (err) { | 953 | if (err) { |
1043 | pr_debug("failed to create perf header attribute\n"); | 954 | pr_debug("failed to create perf header attribute\n"); |
1044 | return err; | 955 | return err; |
@@ -1048,29 +959,39 @@ int event__synthesize_attrs(struct perf_header *self, event__handler_t process, | |||
1048 | return err; | 959 | return err; |
1049 | } | 960 | } |
1050 | 961 | ||
1051 | 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) | ||
1052 | { | 964 | { |
1053 | struct perf_header_attr *attr; | ||
1054 | unsigned int i, ids, n_ids; | 965 | unsigned int i, ids, n_ids; |
966 | struct perf_evsel *evsel; | ||
967 | |||
968 | if (session->evlist == NULL) { | ||
969 | session->evlist = perf_evlist__new(NULL, NULL); | ||
970 | if (session->evlist == NULL) | ||
971 | return -ENOMEM; | ||
972 | } | ||
1055 | 973 | ||
1056 | attr = perf_header_attr__new(&self->attr.attr); | 974 | evsel = perf_evsel__new(&event->attr.attr, |
1057 | if (attr == NULL) | 975 | session->evlist->nr_entries); |
976 | if (evsel == NULL) | ||
1058 | return -ENOMEM; | 977 | return -ENOMEM; |
1059 | 978 | ||
1060 | ids = self->header.size; | 979 | perf_evlist__add(session->evlist, evsel); |
1061 | ids -= (void *)&self->attr.id - (void *)self; | 980 | |
981 | ids = event->header.size; | ||
982 | ids -= (void *)&event->attr.id - (void *)event; | ||
1062 | 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; | ||
1063 | 991 | ||
1064 | for (i = 0; i < n_ids; i++) { | 992 | for (i = 0; i < n_ids; i++) { |
1065 | if (perf_header_attr__add_id(attr, self->attr.id[i]) < 0) { | 993 | perf_evlist__id_add(session->evlist, evsel, 0, i, |
1066 | perf_header_attr__delete(attr); | 994 | event->attr.id[i]); |
1067 | return -ENOMEM; | ||
1068 | } | ||
1069 | } | ||
1070 | |||
1071 | if (perf_header__add_attr(&session->header, attr) < 0) { | ||
1072 | perf_header_attr__delete(attr); | ||
1073 | return -ENOMEM; | ||
1074 | } | 995 | } |
1075 | 996 | ||
1076 | perf_session__update_sample_type(session); | 997 | perf_session__update_sample_type(session); |
@@ -1078,11 +999,11 @@ int event__process_attr(event_t *self, struct perf_session *session) | |||
1078 | return 0; | 999 | return 0; |
1079 | } | 1000 | } |
1080 | 1001 | ||
1081 | int event__synthesize_event_type(u64 event_id, char *name, | 1002 | int perf_event__synthesize_event_type(u64 event_id, char *name, |
1082 | event__handler_t process, | 1003 | perf_event__handler_t process, |
1083 | struct perf_session *session) | 1004 | struct perf_session *session) |
1084 | { | 1005 | { |
1085 | event_t ev; | 1006 | union perf_event ev; |
1086 | size_t size = 0; | 1007 | size_t size = 0; |
1087 | int err = 0; | 1008 | int err = 0; |
1088 | 1009 | ||
@@ -1103,8 +1024,8 @@ int event__synthesize_event_type(u64 event_id, char *name, | |||
1103 | return err; | 1024 | return err; |
1104 | } | 1025 | } |
1105 | 1026 | ||
1106 | int event__synthesize_event_types(event__handler_t process, | 1027 | int perf_event__synthesize_event_types(perf_event__handler_t process, |
1107 | struct perf_session *session) | 1028 | struct perf_session *session) |
1108 | { | 1029 | { |
1109 | struct perf_trace_event_type *type; | 1030 | struct perf_trace_event_type *type; |
1110 | int i, err = 0; | 1031 | int i, err = 0; |
@@ -1112,8 +1033,9 @@ int event__synthesize_event_types(event__handler_t process, | |||
1112 | for (i = 0; i < event_count; i++) { | 1033 | for (i = 0; i < event_count; i++) { |
1113 | type = &events[i]; | 1034 | type = &events[i]; |
1114 | 1035 | ||
1115 | err = event__synthesize_event_type(type->event_id, type->name, | 1036 | err = perf_event__synthesize_event_type(type->event_id, |
1116 | process, session); | 1037 | type->name, process, |
1038 | session); | ||
1117 | if (err) { | 1039 | if (err) { |
1118 | pr_debug("failed to create perf header event type\n"); | 1040 | pr_debug("failed to create perf header event type\n"); |
1119 | return err; | 1041 | return err; |
@@ -1123,28 +1045,28 @@ int event__synthesize_event_types(event__handler_t process, | |||
1123 | return err; | 1045 | return err; |
1124 | } | 1046 | } |
1125 | 1047 | ||
1126 | int event__process_event_type(event_t *self, | 1048 | int perf_event__process_event_type(union perf_event *event, |
1127 | struct perf_session *session __unused) | 1049 | struct perf_session *session __unused) |
1128 | { | 1050 | { |
1129 | 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, |
1130 | self->event_type.event_type.name) < 0) | 1052 | event->event_type.event_type.name) < 0) |
1131 | return -ENOMEM; | 1053 | return -ENOMEM; |
1132 | 1054 | ||
1133 | return 0; | 1055 | return 0; |
1134 | } | 1056 | } |
1135 | 1057 | ||
1136 | int event__synthesize_tracing_data(int fd, struct list_head *pattrs, | 1058 | int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, |
1137 | event__handler_t process, | 1059 | perf_event__handler_t process, |
1138 | struct perf_session *session __unused) | 1060 | struct perf_session *session __unused) |
1139 | { | 1061 | { |
1140 | event_t ev; | 1062 | union perf_event ev; |
1141 | ssize_t size = 0, aligned_size = 0, padding; | 1063 | ssize_t size = 0, aligned_size = 0, padding; |
1142 | int err = 0; | 1064 | int err __used = 0; |
1143 | 1065 | ||
1144 | memset(&ev, 0, sizeof(ev)); | 1066 | memset(&ev, 0, sizeof(ev)); |
1145 | 1067 | ||
1146 | ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; | 1068 | ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; |
1147 | size = read_tracing_data_size(fd, pattrs); | 1069 | size = read_tracing_data_size(fd, &evlist->entries); |
1148 | if (size <= 0) | 1070 | if (size <= 0) |
1149 | return size; | 1071 | return size; |
1150 | aligned_size = ALIGN(size, sizeof(u64)); | 1072 | aligned_size = ALIGN(size, sizeof(u64)); |
@@ -1154,16 +1076,16 @@ int event__synthesize_tracing_data(int fd, struct list_head *pattrs, | |||
1154 | 1076 | ||
1155 | process(&ev, NULL, session); | 1077 | process(&ev, NULL, session); |
1156 | 1078 | ||
1157 | err = read_tracing_data(fd, pattrs); | 1079 | err = read_tracing_data(fd, &evlist->entries); |
1158 | write_padded(fd, NULL, 0, padding); | 1080 | write_padded(fd, NULL, 0, padding); |
1159 | 1081 | ||
1160 | return aligned_size; | 1082 | return aligned_size; |
1161 | } | 1083 | } |
1162 | 1084 | ||
1163 | int event__process_tracing_data(event_t *self, | 1085 | int perf_event__process_tracing_data(union perf_event *event, |
1164 | struct perf_session *session) | 1086 | struct perf_session *session) |
1165 | { | 1087 | { |
1166 | ssize_t size_read, padding, size = self->tracing_data.size; | 1088 | ssize_t size_read, padding, size = event->tracing_data.size; |
1167 | off_t offset = lseek(session->fd, 0, SEEK_CUR); | 1089 | off_t offset = lseek(session->fd, 0, SEEK_CUR); |
1168 | char buf[BUFSIZ]; | 1090 | char buf[BUFSIZ]; |
1169 | 1091 | ||
@@ -1189,12 +1111,12 @@ int event__process_tracing_data(event_t *self, | |||
1189 | return size_read + padding; | 1111 | return size_read + padding; |
1190 | } | 1112 | } |
1191 | 1113 | ||
1192 | int event__synthesize_build_id(struct dso *pos, u16 misc, | 1114 | int perf_event__synthesize_build_id(struct dso *pos, u16 misc, |
1193 | event__handler_t process, | 1115 | perf_event__handler_t process, |
1194 | struct machine *machine, | 1116 | struct machine *machine, |
1195 | struct perf_session *session) | 1117 | struct perf_session *session) |
1196 | { | 1118 | { |
1197 | event_t ev; | 1119 | union perf_event ev; |
1198 | size_t len; | 1120 | size_t len; |
1199 | int err = 0; | 1121 | int err = 0; |
1200 | 1122 | ||
@@ -1217,11 +1139,11 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, | |||
1217 | return err; | 1139 | return err; |
1218 | } | 1140 | } |
1219 | 1141 | ||
1220 | int event__process_build_id(event_t *self, | 1142 | int perf_event__process_build_id(union perf_event *event, |
1221 | struct perf_session *session) | 1143 | struct perf_session *session) |
1222 | { | 1144 | { |
1223 | __event_process_build_id(&self->build_id, | 1145 | __event_process_build_id(&event->build_id, |
1224 | self->build_id.filename, | 1146 | event->build_id.filename, |
1225 | session); | 1147 | session); |
1226 | return 0; | 1148 | return 0; |
1227 | } | 1149 | } |