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