1 #define _FILE_OFFSET_BITS 64 2 3 #include <sys/types.h> 4 #include <byteswap.h> 5 #include <unistd.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <linux/list.h> 9 #include <linux/kernel.h> 10 11 #include "util.h" 12 #include "header.h" 13 #include "../perf.h" 14 #include "trace-event.h" 15 #include "session.h" 16 #include "symbol.h" 17 #include "debug.h" 18 19 /* 20 * Create new perf.data header attribute: 21 */ 22 struct perf_header_attr *perf_header_attr__new(struct perf_event_attr *attr) 23 { 24 struct perf_header_attr *self = malloc(sizeof(*self)); 25 26 if (self != NULL) { 27 self->attr = *attr; 28 self->ids = 0; 29 self->size = 1; 30 self->id = malloc(sizeof(u64)); 31 if (self->id == NULL) { 32 free(self); 33 self = NULL; 34 } 35 } 36 37 return self; 38 } 39 40 void perf_header_attr__delete(struct perf_header_attr *self) 41 { 42 free(self->id); 43 free(self); 44 } 45 46 int perf_header_attr__add_id(struct perf_header_attr *self, u64 id) 47 { 48 int pos = self->ids; 49 50 self->ids++; 51 if (self->ids > self->size) { 52 int nsize = self->size * 2; 53 u64 *nid = realloc(self->id, nsize * sizeof(u64)); 54 55 if (nid == NULL) 56 return -1; 57 58 self->size = nsize; 59 self->id = nid; 60 } 61 self->id[pos] = id; 62 return 0; 63 } 64 65 int perf_header__init(struct perf_header *self) 66 { 67 self->size = 1; 68 self->attr = malloc(sizeof(void *)); 69 return self->attr == NULL ? -ENOMEM : 0; 70 } 71 72 void perf_header__exit(struct perf_header *self) 73 { 74 int i; 75 for (i = 0; i < self->attrs; ++i) 76 perf_header_attr__delete(self->attr[i]); 77 free(self->attr); 78 } 79 80 int perf_header__add_attr(struct perf_header *self, 81 struct perf_header_attr *attr) 82 { 83 if (self->frozen) 84 return -1; 85 86 if (self->attrs == self->size) { 87 int nsize = self->size * 2; 88 struct perf_header_attr **nattr; 89 90 nattr = realloc(self->attr, nsize * sizeof(void *)); 91 if (nattr == NULL) 92 return -1; 93 94 self->size = nsize; 95 self->attr = nattr; 96 } 97 98 self->attr[self->attrs++] = attr; 99 return 0; 100 } 101 102 static int event_count; 103 static struct perf_trace_event_type *events; 104 105 int perf_header__push_event(u64 id, const char *name) 106 { 107 if (strlen(name) > MAX_EVENT_NAME) 108 pr_warning("Event %s will be truncated\n", name); 109 110 if (!events) { 111 events = malloc(sizeof(struct perf_trace_event_type)); 112 if (events == NULL) 113 return -ENOMEM; 114 } else { 115 struct perf_trace_event_type *nevents; 116 117 nevents = realloc(events, (event_count + 1) * sizeof(*events)); 118 if (nevents == NULL) 119 return -ENOMEM; 120 events = nevents; 121 } 122 memset(&events[event_count], 0, sizeof(struct perf_trace_event_type)); 123 events[event_count].event_id = id; 124 strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1); 125 event_count++; 126 return 0; 127 } 128 129 char *perf_header__find_event(u64 id) 130 { 131 int i; 132 for (i = 0 ; i < event_count; i++) { 133 if (events[i].event_id == id) 134 return events[i].name; 135 } 136 return NULL; 137 } 138 139 static const char *__perf_magic = "PERFFILE"; 140 141 #define PERF_MAGIC (*(u64 *)__perf_magic) 142 143 struct perf_file_attr { 144 struct perf_event_attr attr; 145 struct perf_file_section ids; 146 }; 147 148 void perf_header__set_feat(struct perf_header *self, int feat) 149 { 150 set_bit(feat, self->adds_features); 151 } 152 153 bool perf_header__has_feat(const struct perf_header *self, int feat) 154 { 155 return test_bit(feat, self->adds_features); 156 } 157 158 static int do_write(int fd, const void *buf, size_t size) 159 { 160 while (size) { 161 int ret = write(fd, buf, size); 162 163 if (ret < 0) 164 return -errno; 165 166 size -= ret; 167 buf += ret; 168 } 169 170 return 0; 171 } 172 173 #define NAME_ALIGN 64 174 175 static int write_padded(int fd, const void *bf, size_t count, 176 size_t count_aligned) 177 { 178 static const char zero_buf[NAME_ALIGN]; 179 int err = do_write(fd, bf, count); 180 181 if (!err) 182 err = do_write(fd, zero_buf, count_aligned - count); 183 184 return err; 185 } 186 187 #define dsos__for_each_with_build_id(pos, head) \ 188 list_for_each_entry(pos, head, node) \ 189 if (!pos->has_build_id) \ 190 continue; \ 191 else 192 193 static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, 194 u16 misc, int fd) 195 { 196 struct dso *pos; 197 198 dsos__for_each_with_build_id(pos, head) { 199 int err; 200 struct build_id_event b; 201 size_t len; 202 203 if (!pos->hit) 204 continue; 205 len = pos->long_name_len + 1; 206 len = ALIGN(len, NAME_ALIGN); 207 memset(&b, 0, sizeof(b)); 208 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); 209 b.pid = pid; 210 b.header.misc = misc; 211 b.header.size = sizeof(b) + len; 212 err = do_write(fd, &b, sizeof(b)); 213 if (err < 0) 214 return err; 215 err = write_padded(fd, pos->long_name, 216 pos->long_name_len + 1, len); 217 if (err < 0) 218 return err; 219 } 220 221 return 0; 222 } 223 224 static int dsos__write_buildid_table(struct perf_header *header, int fd) 225 { 226 struct perf_session *session = container_of(header, 227 struct perf_session, header); 228 struct rb_node *nd; 229 int err = 0; 230 u16 kmisc, umisc; 231 232 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { 233 struct machine *pos = rb_entry(nd, struct machine, rb_node); 234 if (machine__is_host(pos)) { 235 kmisc = PERF_RECORD_MISC_KERNEL; 236 umisc = PERF_RECORD_MISC_USER; 237 } else { 238 kmisc = PERF_RECORD_MISC_GUEST_KERNEL; 239 umisc = PERF_RECORD_MISC_GUEST_USER; 240 } 241 242 err = __dsos__write_buildid_table(&pos->kernel_dsos, pos->pid, 243 kmisc, fd); 244 if (err == 0) 245 err = __dsos__write_buildid_table(&pos->user_dsos, 246 pos->pid, umisc, fd); 247 if (err) 248 break; 249 } 250 return err; 251 } 252 253 int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, 254 const char *name, bool is_kallsyms) 255 { 256 const size_t size = PATH_MAX; 257 char *filename = malloc(size), 258 *linkname = malloc(size), *targetname; 259 int len, err = -1; 260 261 if (filename == NULL || linkname == NULL) 262 goto out_free; 263 264 len = snprintf(filename, size, "%s%s%s", 265 debugdir, is_kallsyms ? "/" : "", name); 266 if (mkdir_p(filename, 0755)) 267 goto out_free; 268 269 snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id); 270 271 if (access(filename, F_OK)) { 272 if (is_kallsyms) { 273 if (copyfile("/proc/kallsyms", filename)) 274 goto out_free; 275 } else if (link(name, filename) && copyfile(name, filename)) 276 goto out_free; 277 } 278 279 len = snprintf(linkname, size, "%s/.build-id/%.2s", 280 debugdir, sbuild_id); 281 282 if (access(linkname, X_OK) && mkdir_p(linkname, 0755)) 283 goto out_free; 284 285 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2); 286 targetname = filename + strlen(debugdir) - 5; 287 memcpy(targetname, "../..", 5); 288 289 if (symlink(targetname, linkname) == 0) 290 err = 0; 291 out_free: 292 free(filename); 293 free(linkname); 294 return err; 295 } 296 297 static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, 298 const char *name, const char *debugdir, 299 bool is_kallsyms) 300 { 301 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 302 303 build_id__sprintf(build_id, build_id_size, sbuild_id); 304 305 return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms); 306 } 307 308 int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) 309 { 310 const size_t size = PATH_MAX; 311 char *filename = malloc(size), 312 *linkname = malloc(size); 313 int err = -1; 314 315 if (filename == NULL || linkname == NULL) 316 goto out_free; 317 318 snprintf(linkname, size, "%s/.build-id/%.2s/%s", 319 debugdir, sbuild_id, sbuild_id + 2); 320 321 if (access(linkname, F_OK)) 322 goto out_free; 323 324 if (readlink(linkname, filename, size) < 0) 325 goto out_free; 326 327 if (unlink(linkname)) 328 goto out_free; 329 330 /* 331 * Since the link is relative, we must make it absolute: 332 */ 333 snprintf(linkname, size, "%s/.build-id/%.2s/%s", 334 debugdir, sbuild_id, filename); 335 336 if (unlink(linkname)) 337 goto out_free; 338 339 err = 0; 340 out_free: 341 free(filename); 342 free(linkname); 343 return err; 344 } 345 346 static int dso__cache_build_id(struct dso *self, const char *debugdir) 347 { 348 bool is_kallsyms = self->kernel && self->long_name[0] != '/'; 349 350 return build_id_cache__add_b(self->build_id, sizeof(self->build_id), 351 self->long_name, debugdir, is_kallsyms); 352 } 353 354 static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) 355 { 356 struct dso *pos; 357 int err = 0; 358 359 dsos__for_each_with_build_id(pos, head) 360 if (dso__cache_build_id(pos, debugdir)) 361 err = -1; 362 363 return err; 364 } 365 366 static int dsos__cache_build_ids(struct perf_header *self) 367 { 368 struct perf_session *session = container_of(self, 369 struct perf_session, header); 370 struct rb_node *nd; 371 int ret = 0; 372 char debugdir[PATH_MAX]; 373 374 snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"), 375 DEBUG_CACHE_DIR); 376 377 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) 378 return -1; 379 380 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { 381 struct machine *pos = rb_entry(nd, struct machine, rb_node); 382 ret |= __dsos__cache_build_ids(&pos->kernel_dsos, debugdir); 383 ret |= __dsos__cache_build_ids(&pos->user_dsos, debugdir); 384 } 385 return ret ? -1 : 0; 386 } 387 388 static bool dsos__read_build_ids(struct perf_header *self, bool with_hits) 389 { 390 bool ret = false; 391 struct perf_session *session = container_of(self, 392 struct perf_session, header); 393 struct rb_node *nd; 394 395 for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { 396 struct machine *pos = rb_entry(nd, struct machine, rb_node); 397 ret |= __dsos__read_build_ids(&pos->kernel_dsos, with_hits); 398 ret |= __dsos__read_build_ids(&pos->user_dsos, with_hits); 399 } 400 401 return ret; 402 } 403 404 static int perf_header__adds_write(struct perf_header *self, int fd) 405 { 406 int nr_sections; 407 struct perf_file_section *feat_sec; 408 int sec_size; 409 u64 sec_start; 410 int idx = 0, err; 411 412 if (dsos__read_build_ids(self, true)) 413 perf_header__set_feat(self, HEADER_BUILD_ID); 414 415 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 416 if (!nr_sections) 417 return 0; 418 419 feat_sec = calloc(sizeof(*feat_sec), nr_sections); 420 if (feat_sec == NULL) 421 return -ENOMEM; 422 423 sec_size = sizeof(*feat_sec) * nr_sections; 424 425 sec_start = self->data_offset + self->data_size; 426 lseek(fd, sec_start + sec_size, SEEK_SET); 427 428 if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { 429 struct perf_file_section *trace_sec; 430 431 trace_sec = &feat_sec[idx++]; 432 433 /* Write trace info */ 434 trace_sec->offset = lseek(fd, 0, SEEK_CUR); 435 read_tracing_data(fd, attrs, nr_counters); 436 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; 437 } 438 439 if (perf_header__has_feat(self, HEADER_BUILD_ID)) { 440 struct perf_file_section *buildid_sec; 441 442 buildid_sec = &feat_sec[idx++]; 443 444 /* Write build-ids */ 445 buildid_sec->offset = lseek(fd, 0, SEEK_CUR); 446 err = dsos__write_buildid_table(self, fd); 447 if (err < 0) { 448 pr_debug("failed to write buildid table\n"); 449 goto out_free; 450 } 451 buildid_sec->size = lseek(fd, 0, SEEK_CUR) - 452 buildid_sec->offset; 453 dsos__cache_build_ids(self); 454 } 455 456 lseek(fd, sec_start, SEEK_SET); 457 err = do_write(fd, feat_sec, sec_size); 458 if (err < 0) 459 pr_debug("failed to write feature section\n"); 460 out_free: 461 free(feat_sec); 462 return err; 463 } 464 465 int perf_header__write_pipe(int fd) 466 { 467 struct perf_pipe_file_header f_header; 468 int err; 469 470 f_header = (struct perf_pipe_file_header){ 471 .magic = PERF_MAGIC, 472 .size = sizeof(f_header), 473 }; 474 475 err = do_write(fd, &f_header, sizeof(f_header)); 476 if (err < 0) { 477 pr_debug("failed to write perf pipe header\n"); 478 return err; 479 } 480 481 return 0; 482 } 483 484 int perf_header__write(struct perf_header *self, int fd, bool at_exit) 485 { 486 struct perf_file_header f_header; 487 struct perf_file_attr f_attr; 488 struct perf_header_attr *attr; 489 int i, err; 490 491 lseek(fd, sizeof(f_header), SEEK_SET); 492 493 494 for (i = 0; i < self->attrs; i++) { 495 attr = self->attr[i]; 496 497 attr->id_offset = lseek(fd, 0, SEEK_CUR); 498 err = do_write(fd, attr->id, attr->ids * sizeof(u64)); 499 if (err < 0) { 500 pr_debug("failed to write perf header\n"); 501 return err; 502 } 503 } 504 505 506 self->attr_offset = lseek(fd, 0, SEEK_CUR); 507 508 for (i = 0; i < self->attrs; i++) { 509 attr = self->attr[i]; 510 511 f_attr = (struct perf_file_attr){ 512 .attr = attr->attr, 513 .ids = { 514 .offset = attr->id_offset, 515 .size = attr->ids * sizeof(u64), 516 } 517 }; 518 err = do_write(fd, &f_attr, sizeof(f_attr)); 519 if (err < 0) { 520 pr_debug("failed to write perf header attribute\n"); 521 return err; 522 } 523 } 524 525 self->event_offset = lseek(fd, 0, SEEK_CUR); 526 self->event_size = event_count * sizeof(struct perf_trace_event_type); 527 if (events) { 528 err = do_write(fd, events, self->event_size); 529 if (err < 0) { 530 pr_debug("failed to write perf header events\n"); 531 return err; 532 } 533 } 534 535 self->data_offset = lseek(fd, 0, SEEK_CUR); 536 537 if (at_exit) { 538 err = perf_header__adds_write(self, fd); 539 if (err < 0) 540 return err; 541 } 542 543 f_header = (struct perf_file_header){ 544 .magic = PERF_MAGIC, 545 .size = sizeof(f_header), 546 .attr_size = sizeof(f_attr), 547 .attrs = { 548 .offset = self->attr_offset, 549 .size = self->attrs * sizeof(f_attr), 550 }, 551 .data = { 552 .offset = self->data_offset, 553 .size = self->data_size, 554 }, 555 .event_types = { 556 .offset = self->event_offset, 557 .size = self->event_size, 558 }, 559 }; 560 561 memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features)); 562 563 lseek(fd, 0, SEEK_SET); 564 err = do_write(fd, &f_header, sizeof(f_header)); 565 if (err < 0) { 566 pr_debug("failed to write perf header\n"); 567 return err; 568 } 569 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 570 571 self->frozen = 1; 572 return 0; 573 } 574 575 static int perf_header__getbuffer64(struct perf_header *self, 576 int fd, void *buf, size_t size) 577 { 578 if (do_read(fd, buf, size) <= 0) 579 return -1; 580 581 if (self->needs_swap) 582 mem_bswap_64(buf, size); 583 584 return 0; 585 } 586 587 int perf_header__process_sections(struct perf_header *self, int fd, 588 int (*process)(struct perf_file_section *self, 589 struct perf_header *ph, 590 int feat, int fd)) 591 { 592 struct perf_file_section *feat_sec; 593 int nr_sections; 594 int sec_size; 595 int idx = 0; 596 int err = -1, feat = 1; 597 598 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 599 if (!nr_sections) 600 return 0; 601 602 feat_sec = calloc(sizeof(*feat_sec), nr_sections); 603 if (!feat_sec) 604 return -1; 605 606 sec_size = sizeof(*feat_sec) * nr_sections; 607 608 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 609 610 if (perf_header__getbuffer64(self, fd, feat_sec, sec_size)) 611 goto out_free; 612 613 err = 0; 614 while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { 615 if (perf_header__has_feat(self, feat)) { 616 struct perf_file_section *sec = &feat_sec[idx++]; 617 618 err = process(sec, self, feat, fd); 619 if (err < 0) 620 break; 621 } 622 ++feat; 623 } 624 out_free: 625 free(feat_sec); 626 return err; 627 } 628 629 int perf_file_header__read(struct perf_file_header *self, 630 struct perf_header *ph, int fd) 631 { 632 lseek(fd, 0, SEEK_SET); 633 634 if (do_read(fd, self, sizeof(*self)) <= 0 || 635 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 636 return -1; 637 638 if (self->attr_size != sizeof(struct perf_file_attr)) { 639 u64 attr_size = bswap_64(self->attr_size); 640 641 if (attr_size != sizeof(struct perf_file_attr)) 642 return -1; 643 644 mem_bswap_64(self, offsetof(struct perf_file_header, 645 adds_features)); 646 ph->needs_swap = true; 647 } 648 649 if (self->size != sizeof(*self)) { 650 /* Support the previous format */ 651 if (self->size == offsetof(typeof(*self), adds_features)) 652 bitmap_zero(self->adds_features, HEADER_FEAT_BITS); 653 else 654 return -1; 655 } 656 657 memcpy(&ph->adds_features, &self->adds_features, 658 sizeof(ph->adds_features)); 659 /* 660 * FIXME: hack that assumes that if we need swap the perf.data file 661 * may be coming from an arch with a different word-size, ergo different 662 * DEFINE_BITMAP format, investigate more later, but for now its mostly 663 * safe to assume that we have a build-id section. Trace files probably 664 * have several other issues in this realm anyway... 665 */ 666 if (ph->needs_swap) { 667 memset(&ph->adds_features, 0, sizeof(ph->adds_features)); 668 perf_header__set_feat(ph, HEADER_BUILD_ID); 669 } 670 671 ph->event_offset = self->event_types.offset; 672 ph->event_size = self->event_types.size; 673 ph->data_offset = self->data.offset; 674 ph->data_size = self->data.size; 675 return 0; 676 } 677 678 static int __event_process_build_id(struct build_id_event *bev, 679 char *filename, 680 struct perf_session *session) 681 { 682 int err = -1; 683 struct list_head *head; 684 struct machine *machine; 685 u16 misc; 686 struct dso *dso; 687 enum dso_kernel_type dso_type; 688 689 machine = perf_session__findnew_machine(session, bev->pid); 690 if (!machine) 691 goto out; 692 693 misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 694 695 switch (misc) { 696 case PERF_RECORD_MISC_KERNEL: 697 dso_type = DSO_TYPE_KERNEL; 698 head = &machine->kernel_dsos; 699 break; 700 case PERF_RECORD_MISC_GUEST_KERNEL: 701 dso_type = DSO_TYPE_GUEST_KERNEL; 702 head = &machine->kernel_dsos; 703 break; 704 case PERF_RECORD_MISC_USER: 705 case PERF_RECORD_MISC_GUEST_USER: 706 dso_type = DSO_TYPE_USER; 707 head = &machine->user_dsos; 708 break; 709 default: 710 goto out; 711 } 712 713 dso = __dsos__findnew(head, filename); 714 if (dso != NULL) { 715 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 716 717 dso__set_build_id(dso, &bev->build_id); 718 719 if (filename[0] == '[') 720 dso->kernel = dso_type; 721 722 build_id__sprintf(dso->build_id, sizeof(dso->build_id), 723 sbuild_id); 724 pr_debug("build id event received for %s: %s\n", 725 dso->long_name, sbuild_id); 726 } 727 728 err = 0; 729 out: 730 return err; 731 } 732 733 static int perf_header__read_build_ids(struct perf_header *self, 734 int input, u64 offset, u64 size) 735 { 736 struct perf_session *session = container_of(self, 737 struct perf_session, header); 738 struct build_id_event bev; 739 char filename[PATH_MAX]; 740 u64 limit = offset + size; 741 int err = -1; 742 743 while (offset < limit) { 744 ssize_t len; 745 746 if (read(input, &bev, sizeof(bev)) != sizeof(bev)) 747 goto out; 748 749 if (self->needs_swap) 750 perf_event_header__bswap(&bev.header); 751 752 len = bev.header.size - sizeof(bev); 753 if (read(input, filename, len) != len) 754 goto out; 755 756 __event_process_build_id(&bev, filename, session); 757 758 offset += bev.header.size; 759 } 760 err = 0; 761 out: 762 return err; 763 } 764 765 static int perf_file_section__process(struct perf_file_section *self, 766 struct perf_header *ph, 767 int feat, int fd) 768 { 769 if (lseek(fd, self->offset, SEEK_SET) == (off_t)-1) { 770 pr_debug("Failed to lseek to %Ld offset for feature %d, " 771 "continuing...\n", self->offset, feat); 772 return 0; 773 } 774 775 switch (feat) { 776 case HEADER_TRACE_INFO: 777 trace_report(fd, false); 778 break; 779 780 case HEADER_BUILD_ID: 781 if (perf_header__read_build_ids(ph, fd, self->offset, self->size)) 782 pr_debug("Failed to read buildids, continuing...\n"); 783 break; 784 default: 785 pr_debug("unknown feature %d, continuing...\n", feat); 786 } 787 788 return 0; 789 } 790 791 static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, 792 struct perf_header *ph, int fd, 793 bool repipe) 794 { 795 if (do_read(fd, self, sizeof(*self)) <= 0 || 796 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 797 return -1; 798 799 if (repipe && do_write(STDOUT_FILENO, self, sizeof(*self)) < 0) 800 return -1; 801 802 if (self->size != sizeof(*self)) { 803 u64 size = bswap_64(self->size); 804 805 if (size != sizeof(*self)) 806 return -1; 807 808 ph->needs_swap = true; 809 } 810 811 return 0; 812 } 813 814 static int perf_header__read_pipe(struct perf_session *session, int fd) 815 { 816 struct perf_header *self = &session->header; 817 struct perf_pipe_file_header f_header; 818 819 if (perf_file_header__read_pipe(&f_header, self, fd, 820 session->repipe) < 0) { 821 pr_debug("incompatible file format\n"); 822 return -EINVAL; 823 } 824 825 session->fd = fd; 826 827 return 0; 828 } 829 830 int perf_header__read(struct perf_session *session, int fd) 831 { 832 struct perf_header *self = &session->header; 833 struct perf_file_header f_header; 834 struct perf_file_attr f_attr; 835 u64 f_id; 836 int nr_attrs, nr_ids, i, j; 837 838 if (session->fd_pipe) 839 return perf_header__read_pipe(session, fd); 840 841 if (perf_file_header__read(&f_header, self, fd) < 0) { 842 pr_debug("incompatible file format\n"); 843 return -EINVAL; 844 } 845 846 nr_attrs = f_header.attrs.size / sizeof(f_attr); 847 lseek(fd, f_header.attrs.offset, SEEK_SET); 848 849 for (i = 0; i < nr_attrs; i++) { 850 struct perf_header_attr *attr; 851 off_t tmp; 852 853 if (perf_header__getbuffer64(self, fd, &f_attr, sizeof(f_attr))) 854 goto out_errno; 855 856 tmp = lseek(fd, 0, SEEK_CUR); 857 858 attr = perf_header_attr__new(&f_attr.attr); 859 if (attr == NULL) 860 return -ENOMEM; 861 862 nr_ids = f_attr.ids.size / sizeof(u64); 863 lseek(fd, f_attr.ids.offset, SEEK_SET); 864 865 for (j = 0; j < nr_ids; j++) { 866 if (perf_header__getbuffer64(self, fd, &f_id, sizeof(f_id))) 867 goto out_errno; 868 869 if (perf_header_attr__add_id(attr, f_id) < 0) { 870 perf_header_attr__delete(attr); 871 return -ENOMEM; 872 } 873 } 874 if (perf_header__add_attr(self, attr) < 0) { 875 perf_header_attr__delete(attr); 876 return -ENOMEM; 877 } 878 879 lseek(fd, tmp, SEEK_SET); 880 } 881 882 if (f_header.event_types.size) { 883 lseek(fd, f_header.event_types.offset, SEEK_SET); 884 events = malloc(f_header.event_types.size); 885 if (events == NULL) 886 return -ENOMEM; 887 if (perf_header__getbuffer64(self, fd, events, 888 f_header.event_types.size)) 889 goto out_errno; 890 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 891 } 892 893 perf_header__process_sections(self, fd, perf_file_section__process); 894 895 lseek(fd, self->data_offset, SEEK_SET); 896 897 self->frozen = 1; 898 return 0; 899 out_errno: 900 return -errno; 901 } 902 903 u64 perf_header__sample_type(struct perf_header *header) 904 { 905 u64 type = 0; 906 int i; 907 908 for (i = 0; i < header->attrs; i++) { 909 struct perf_header_attr *attr = header->attr[i]; 910 911 if (!type) 912 type = attr->attr.sample_type; 913 else if (type != attr->attr.sample_type) 914 die("non matching sample_type"); 915 } 916 917 return type; 918 } 919 920 struct perf_event_attr * 921 perf_header__find_attr(u64 id, struct perf_header *header) 922 { 923 int i; 924 925 /* 926 * We set id to -1 if the data file doesn't contain sample 927 * ids. Check for this and avoid walking through the entire 928 * list of ids which may be large. 929 */ 930 if (id == -1ULL) 931 return NULL; 932 933 for (i = 0; i < header->attrs; i++) { 934 struct perf_header_attr *attr = header->attr[i]; 935 int j; 936 937 for (j = 0; j < attr->ids; j++) { 938 if (attr->id[j] == id) 939 return &attr->attr; 940 } 941 } 942 943 return NULL; 944 } 945 946 int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, 947 event__handler_t process, 948 struct perf_session *session) 949 { 950 event_t *ev; 951 size_t size; 952 int err; 953 954 size = sizeof(struct perf_event_attr); 955 size = ALIGN(size, sizeof(u64)); 956 size += sizeof(struct perf_event_header); 957 size += ids * sizeof(u64); 958 959 ev = malloc(size); 960 961 ev->attr.attr = *attr; 962 memcpy(ev->attr.id, id, ids * sizeof(u64)); 963 964 ev->attr.header.type = PERF_RECORD_HEADER_ATTR; 965 ev->attr.header.size = size; 966 967 err = process(ev, session); 968 969 free(ev); 970 971 return err; 972 } 973 974 int event__synthesize_attrs(struct perf_header *self, 975 event__handler_t process, 976 struct perf_session *session) 977 { 978 struct perf_header_attr *attr; 979 int i, err = 0; 980 981 for (i = 0; i < self->attrs; i++) { 982 attr = self->attr[i]; 983 984 err = event__synthesize_attr(&attr->attr, attr->ids, attr->id, 985 process, session); 986 if (err) { 987 pr_debug("failed to create perf header attribute\n"); 988 return err; 989 } 990 } 991 992 return err; 993 } 994 995 int event__process_attr(event_t *self, struct perf_session *session) 996 { 997 struct perf_header_attr *attr; 998 unsigned int i, ids, n_ids; 999 1000 attr = perf_header_attr__new(&self->attr.attr); 1001 if (attr == NULL) 1002 return -ENOMEM; 1003 1004 ids = self->header.size; 1005 ids -= (void *)&self->attr.id - (void *)self; 1006 n_ids = ids / sizeof(u64); 1007 1008 for (i = 0; i < n_ids; i++) { 1009 if (perf_header_attr__add_id(attr, self->attr.id[i]) < 0) { 1010 perf_header_attr__delete(attr); 1011 return -ENOMEM; 1012 } 1013 } 1014 1015 if (perf_header__add_attr(&session->header, attr) < 0) { 1016 perf_header_attr__delete(attr); 1017 return -ENOMEM; 1018 } 1019 1020 perf_session__update_sample_type(session); 1021 1022 return 0; 1023 } 1024 1025 int event__synthesize_event_type(u64 event_id, char *name, 1026 event__handler_t process, 1027 struct perf_session *session) 1028 { 1029 event_t ev; 1030 size_t size = 0; 1031 int err = 0; 1032 1033 memset(&ev, 0, sizeof(ev)); 1034 1035 ev.event_type.event_type.event_id = event_id; 1036 memset(ev.event_type.event_type.name, 0, MAX_EVENT_NAME); 1037 strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1); 1038 1039 ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; 1040 size = strlen(name); 1041 size = ALIGN(size, sizeof(u64)); 1042 ev.event_type.header.size = sizeof(ev.event_type) - 1043 (sizeof(ev.event_type.event_type.name) - size); 1044 1045 err = process(&ev, session); 1046 1047 return err; 1048 } 1049 1050 int event__synthesize_event_types(event__handler_t process, 1051 struct perf_session *session) 1052 { 1053 struct perf_trace_event_type *type; 1054 int i, err = 0; 1055 1056 for (i = 0; i < event_count; i++) { 1057 type = &events[i]; 1058 1059 err = event__synthesize_event_type(type->event_id, type->name, 1060 process, session); 1061 if (err) { 1062 pr_debug("failed to create perf header event type\n"); 1063 return err; 1064 } 1065 } 1066 1067 return err; 1068 } 1069 1070 int event__process_event_type(event_t *self, 1071 struct perf_session *session __unused) 1072 { 1073 if (perf_header__push_event(self->event_type.event_type.event_id, 1074 self->event_type.event_type.name) < 0) 1075 return -ENOMEM; 1076 1077 return 0; 1078 } 1079 1080 int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, 1081 int nb_events, 1082 event__handler_t process, 1083 struct perf_session *session __unused) 1084 { 1085 event_t ev; 1086 ssize_t size = 0, aligned_size = 0, padding; 1087 int err = 0; 1088 1089 memset(&ev, 0, sizeof(ev)); 1090 1091 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; 1092 size = read_tracing_data_size(fd, pattrs, nb_events); 1093 if (size <= 0) 1094 return size; 1095 aligned_size = ALIGN(size, sizeof(u64)); 1096 padding = aligned_size - size; 1097 ev.tracing_data.header.size = sizeof(ev.tracing_data); 1098 ev.tracing_data.size = aligned_size; 1099 1100 process(&ev, session); 1101 1102 err = read_tracing_data(fd, pattrs, nb_events); 1103 write_padded(fd, NULL, 0, padding); 1104 1105 return aligned_size; 1106 } 1107 1108 int event__process_tracing_data(event_t *self, 1109 struct perf_session *session) 1110 { 1111 ssize_t size_read, padding, size = self->tracing_data.size; 1112 off_t offset = lseek(session->fd, 0, SEEK_CUR); 1113 char buf[BUFSIZ]; 1114 1115 /* setup for reading amidst mmap */ 1116 lseek(session->fd, offset + sizeof(struct tracing_data_event), 1117 SEEK_SET); 1118 1119 size_read = trace_report(session->fd, session->repipe); 1120 1121 padding = ALIGN(size_read, sizeof(u64)) - size_read; 1122 1123 if (read(session->fd, buf, padding) < 0) 1124 die("reading input file"); 1125 if (session->repipe) { 1126 int retw = write(STDOUT_FILENO, buf, padding); 1127 if (retw <= 0 || retw != padding) 1128 die("repiping tracing data padding"); 1129 } 1130 1131 if (size_read + padding != size) 1132 die("tracing data size mismatch"); 1133 1134 return size_read + padding; 1135 } 1136 1137 int event__synthesize_build_id(struct dso *pos, u16 misc, 1138 event__handler_t process, 1139 struct machine *machine, 1140 struct perf_session *session) 1141 { 1142 event_t ev; 1143 size_t len; 1144 int err = 0; 1145 1146 if (!pos->hit) 1147 return err; 1148 1149 memset(&ev, 0, sizeof(ev)); 1150 1151 len = pos->long_name_len + 1; 1152 len = ALIGN(len, NAME_ALIGN); 1153 memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); 1154 ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; 1155 ev.build_id.header.misc = misc; 1156 ev.build_id.pid = machine->pid; 1157 ev.build_id.header.size = sizeof(ev.build_id) + len; 1158 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); 1159 1160 err = process(&ev, session); 1161 1162 return err; 1163 } 1164 1165 int event__process_build_id(event_t *self, 1166 struct perf_session *session) 1167 { 1168 __event_process_build_id(&self->build_id, 1169 self->build_id.filename, 1170 session); 1171 return 0; 1172 } 1173