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 #define MAX_EVENT_NAME 64 103 104 struct perf_trace_event_type { 105 u64 event_id; 106 char name[MAX_EVENT_NAME]; 107 }; 108 109 static int event_count; 110 static struct perf_trace_event_type *events; 111 112 int perf_header__push_event(u64 id, const char *name) 113 { 114 if (strlen(name) > MAX_EVENT_NAME) 115 pr_warning("Event %s will be truncated\n", name); 116 117 if (!events) { 118 events = malloc(sizeof(struct perf_trace_event_type)); 119 if (events == NULL) 120 return -ENOMEM; 121 } else { 122 struct perf_trace_event_type *nevents; 123 124 nevents = realloc(events, (event_count + 1) * sizeof(*events)); 125 if (nevents == NULL) 126 return -ENOMEM; 127 events = nevents; 128 } 129 memset(&events[event_count], 0, sizeof(struct perf_trace_event_type)); 130 events[event_count].event_id = id; 131 strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1); 132 event_count++; 133 return 0; 134 } 135 136 char *perf_header__find_event(u64 id) 137 { 138 int i; 139 for (i = 0 ; i < event_count; i++) { 140 if (events[i].event_id == id) 141 return events[i].name; 142 } 143 return NULL; 144 } 145 146 static const char *__perf_magic = "PERFFILE"; 147 148 #define PERF_MAGIC (*(u64 *)__perf_magic) 149 150 struct perf_file_attr { 151 struct perf_event_attr attr; 152 struct perf_file_section ids; 153 }; 154 155 void perf_header__set_feat(struct perf_header *self, int feat) 156 { 157 set_bit(feat, self->adds_features); 158 } 159 160 bool perf_header__has_feat(const struct perf_header *self, int feat) 161 { 162 return test_bit(feat, self->adds_features); 163 } 164 165 static int do_write(int fd, const void *buf, size_t size) 166 { 167 while (size) { 168 int ret = write(fd, buf, size); 169 170 if (ret < 0) 171 return -errno; 172 173 size -= ret; 174 buf += ret; 175 } 176 177 return 0; 178 } 179 180 #define NAME_ALIGN 64 181 182 static int write_padded(int fd, const void *bf, size_t count, 183 size_t count_aligned) 184 { 185 static const char zero_buf[NAME_ALIGN]; 186 int err = do_write(fd, bf, count); 187 188 if (!err) 189 err = do_write(fd, zero_buf, count_aligned - count); 190 191 return err; 192 } 193 194 #define dsos__for_each_with_build_id(pos, head) \ 195 list_for_each_entry(pos, head, node) \ 196 if (!pos->has_build_id) \ 197 continue; \ 198 else 199 200 static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) 201 { 202 struct dso *pos; 203 204 dsos__for_each_with_build_id(pos, head) { 205 int err; 206 struct build_id_event b; 207 size_t len; 208 209 if (!pos->hit) 210 continue; 211 len = pos->long_name_len + 1; 212 len = ALIGN(len, NAME_ALIGN); 213 memset(&b, 0, sizeof(b)); 214 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); 215 b.header.misc = misc; 216 b.header.size = sizeof(b) + len; 217 err = do_write(fd, &b, sizeof(b)); 218 if (err < 0) 219 return err; 220 err = write_padded(fd, pos->long_name, 221 pos->long_name_len + 1, len); 222 if (err < 0) 223 return err; 224 } 225 226 return 0; 227 } 228 229 static int dsos__write_buildid_table(int fd) 230 { 231 int err = __dsos__write_buildid_table(&dsos__kernel, 232 PERF_RECORD_MISC_KERNEL, fd); 233 if (err == 0) 234 err = __dsos__write_buildid_table(&dsos__user, 235 PERF_RECORD_MISC_USER, fd); 236 return err; 237 } 238 239 int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, 240 const char *name, bool is_kallsyms) 241 { 242 const size_t size = PATH_MAX; 243 char *filename = malloc(size), 244 *linkname = malloc(size), *targetname; 245 int len, err = -1; 246 247 if (filename == NULL || linkname == NULL) 248 goto out_free; 249 250 len = snprintf(filename, size, "%s%s%s", 251 debugdir, is_kallsyms ? "/" : "", name); 252 if (mkdir_p(filename, 0755)) 253 goto out_free; 254 255 snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id); 256 257 if (access(filename, F_OK)) { 258 if (is_kallsyms) { 259 if (copyfile("/proc/kallsyms", filename)) 260 goto out_free; 261 } else if (link(name, filename) && copyfile(name, filename)) 262 goto out_free; 263 } 264 265 len = snprintf(linkname, size, "%s/.build-id/%.2s", 266 debugdir, sbuild_id); 267 268 if (access(linkname, X_OK) && mkdir_p(linkname, 0755)) 269 goto out_free; 270 271 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2); 272 targetname = filename + strlen(debugdir) - 5; 273 memcpy(targetname, "../..", 5); 274 275 if (symlink(targetname, linkname) == 0) 276 err = 0; 277 out_free: 278 free(filename); 279 free(linkname); 280 return err; 281 } 282 283 static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, 284 const char *name, const char *debugdir, 285 bool is_kallsyms) 286 { 287 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 288 289 build_id__sprintf(build_id, build_id_size, sbuild_id); 290 291 return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms); 292 } 293 294 int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) 295 { 296 const size_t size = PATH_MAX; 297 char *filename = malloc(size), 298 *linkname = malloc(size); 299 int err = -1; 300 301 if (filename == NULL || linkname == NULL) 302 goto out_free; 303 304 snprintf(linkname, size, "%s/.build-id/%.2s/%s", 305 debugdir, sbuild_id, sbuild_id + 2); 306 307 if (access(linkname, F_OK)) 308 goto out_free; 309 310 if (readlink(linkname, filename, size) < 0) 311 goto out_free; 312 313 if (unlink(linkname)) 314 goto out_free; 315 316 /* 317 * Since the link is relative, we must make it absolute: 318 */ 319 snprintf(linkname, size, "%s/.build-id/%.2s/%s", 320 debugdir, sbuild_id, filename); 321 322 if (unlink(linkname)) 323 goto out_free; 324 325 err = 0; 326 out_free: 327 free(filename); 328 free(linkname); 329 return err; 330 } 331 332 static int dso__cache_build_id(struct dso *self, const char *debugdir) 333 { 334 bool is_kallsyms = self->kernel && self->long_name[0] != '/'; 335 336 return build_id_cache__add_b(self->build_id, sizeof(self->build_id), 337 self->long_name, debugdir, is_kallsyms); 338 } 339 340 static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) 341 { 342 struct dso *pos; 343 int err = 0; 344 345 dsos__for_each_with_build_id(pos, head) 346 if (dso__cache_build_id(pos, debugdir)) 347 err = -1; 348 349 return err; 350 } 351 352 static int dsos__cache_build_ids(void) 353 { 354 int err_kernel, err_user; 355 char debugdir[PATH_MAX]; 356 357 snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"), 358 DEBUG_CACHE_DIR); 359 360 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) 361 return -1; 362 363 err_kernel = __dsos__cache_build_ids(&dsos__kernel, debugdir); 364 err_user = __dsos__cache_build_ids(&dsos__user, debugdir); 365 return err_kernel || err_user ? -1 : 0; 366 } 367 368 static int perf_header__adds_write(struct perf_header *self, int fd) 369 { 370 int nr_sections; 371 struct perf_file_section *feat_sec; 372 int sec_size; 373 u64 sec_start; 374 int idx = 0, err; 375 376 if (dsos__read_build_ids(true)) 377 perf_header__set_feat(self, HEADER_BUILD_ID); 378 379 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 380 if (!nr_sections) 381 return 0; 382 383 feat_sec = calloc(sizeof(*feat_sec), nr_sections); 384 if (feat_sec == NULL) 385 return -ENOMEM; 386 387 sec_size = sizeof(*feat_sec) * nr_sections; 388 389 sec_start = self->data_offset + self->data_size; 390 lseek(fd, sec_start + sec_size, SEEK_SET); 391 392 if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { 393 struct perf_file_section *trace_sec; 394 395 trace_sec = &feat_sec[idx++]; 396 397 /* Write trace info */ 398 trace_sec->offset = lseek(fd, 0, SEEK_CUR); 399 read_tracing_data(fd, attrs, nr_counters); 400 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; 401 } 402 403 404 if (perf_header__has_feat(self, HEADER_BUILD_ID)) { 405 struct perf_file_section *buildid_sec; 406 407 buildid_sec = &feat_sec[idx++]; 408 409 /* Write build-ids */ 410 buildid_sec->offset = lseek(fd, 0, SEEK_CUR); 411 err = dsos__write_buildid_table(fd); 412 if (err < 0) { 413 pr_debug("failed to write buildid table\n"); 414 goto out_free; 415 } 416 buildid_sec->size = lseek(fd, 0, SEEK_CUR) - 417 buildid_sec->offset; 418 dsos__cache_build_ids(); 419 } 420 421 lseek(fd, sec_start, SEEK_SET); 422 err = do_write(fd, feat_sec, sec_size); 423 if (err < 0) 424 pr_debug("failed to write feature section\n"); 425 out_free: 426 free(feat_sec); 427 return err; 428 } 429 430 int perf_header__write(struct perf_header *self, int fd, bool at_exit) 431 { 432 struct perf_file_header f_header; 433 struct perf_file_attr f_attr; 434 struct perf_header_attr *attr; 435 int i, err; 436 437 lseek(fd, sizeof(f_header), SEEK_SET); 438 439 440 for (i = 0; i < self->attrs; i++) { 441 attr = self->attr[i]; 442 443 attr->id_offset = lseek(fd, 0, SEEK_CUR); 444 err = do_write(fd, attr->id, attr->ids * sizeof(u64)); 445 if (err < 0) { 446 pr_debug("failed to write perf header\n"); 447 return err; 448 } 449 } 450 451 452 self->attr_offset = lseek(fd, 0, SEEK_CUR); 453 454 for (i = 0; i < self->attrs; i++) { 455 attr = self->attr[i]; 456 457 f_attr = (struct perf_file_attr){ 458 .attr = attr->attr, 459 .ids = { 460 .offset = attr->id_offset, 461 .size = attr->ids * sizeof(u64), 462 } 463 }; 464 err = do_write(fd, &f_attr, sizeof(f_attr)); 465 if (err < 0) { 466 pr_debug("failed to write perf header attribute\n"); 467 return err; 468 } 469 } 470 471 self->event_offset = lseek(fd, 0, SEEK_CUR); 472 self->event_size = event_count * sizeof(struct perf_trace_event_type); 473 if (events) { 474 err = do_write(fd, events, self->event_size); 475 if (err < 0) { 476 pr_debug("failed to write perf header events\n"); 477 return err; 478 } 479 } 480 481 self->data_offset = lseek(fd, 0, SEEK_CUR); 482 483 if (at_exit) { 484 err = perf_header__adds_write(self, fd); 485 if (err < 0) 486 return err; 487 } 488 489 f_header = (struct perf_file_header){ 490 .magic = PERF_MAGIC, 491 .size = sizeof(f_header), 492 .attr_size = sizeof(f_attr), 493 .attrs = { 494 .offset = self->attr_offset, 495 .size = self->attrs * sizeof(f_attr), 496 }, 497 .data = { 498 .offset = self->data_offset, 499 .size = self->data_size, 500 }, 501 .event_types = { 502 .offset = self->event_offset, 503 .size = self->event_size, 504 }, 505 }; 506 507 memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features)); 508 509 lseek(fd, 0, SEEK_SET); 510 err = do_write(fd, &f_header, sizeof(f_header)); 511 if (err < 0) { 512 pr_debug("failed to write perf header\n"); 513 return err; 514 } 515 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 516 517 self->frozen = 1; 518 return 0; 519 } 520 521 static int do_read(int fd, void *buf, size_t size) 522 { 523 while (size) { 524 int ret = read(fd, buf, size); 525 526 if (ret <= 0) 527 return -1; 528 529 size -= ret; 530 buf += ret; 531 } 532 533 return 0; 534 } 535 536 static int perf_header__getbuffer64(struct perf_header *self, 537 int fd, void *buf, size_t size) 538 { 539 if (do_read(fd, buf, size)) 540 return -1; 541 542 if (self->needs_swap) 543 mem_bswap_64(buf, size); 544 545 return 0; 546 } 547 548 int perf_header__process_sections(struct perf_header *self, int fd, 549 int (*process)(struct perf_file_section *self, 550 struct perf_header *ph, 551 int feat, int fd)) 552 { 553 struct perf_file_section *feat_sec; 554 int nr_sections; 555 int sec_size; 556 int idx = 0; 557 int err = -1, feat = 1; 558 559 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 560 if (!nr_sections) 561 return 0; 562 563 feat_sec = calloc(sizeof(*feat_sec), nr_sections); 564 if (!feat_sec) 565 return -1; 566 567 sec_size = sizeof(*feat_sec) * nr_sections; 568 569 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 570 571 if (perf_header__getbuffer64(self, fd, feat_sec, sec_size)) 572 goto out_free; 573 574 err = 0; 575 while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { 576 if (perf_header__has_feat(self, feat)) { 577 struct perf_file_section *sec = &feat_sec[idx++]; 578 579 err = process(sec, self, feat, fd); 580 if (err < 0) 581 break; 582 } 583 ++feat; 584 } 585 out_free: 586 free(feat_sec); 587 return err; 588 } 589 590 int perf_file_header__read(struct perf_file_header *self, 591 struct perf_header *ph, int fd) 592 { 593 lseek(fd, 0, SEEK_SET); 594 595 if (do_read(fd, self, sizeof(*self)) || 596 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 597 return -1; 598 599 if (self->attr_size != sizeof(struct perf_file_attr)) { 600 u64 attr_size = bswap_64(self->attr_size); 601 602 if (attr_size != sizeof(struct perf_file_attr)) 603 return -1; 604 605 mem_bswap_64(self, offsetof(struct perf_file_header, 606 adds_features)); 607 ph->needs_swap = true; 608 } 609 610 if (self->size != sizeof(*self)) { 611 /* Support the previous format */ 612 if (self->size == offsetof(typeof(*self), adds_features)) 613 bitmap_zero(self->adds_features, HEADER_FEAT_BITS); 614 else 615 return -1; 616 } 617 618 memcpy(&ph->adds_features, &self->adds_features, 619 sizeof(ph->adds_features)); 620 /* 621 * FIXME: hack that assumes that if we need swap the perf.data file 622 * may be coming from an arch with a different word-size, ergo different 623 * DEFINE_BITMAP format, investigate more later, but for now its mostly 624 * safe to assume that we have a build-id section. Trace files probably 625 * have several other issues in this realm anyway... 626 */ 627 if (ph->needs_swap) { 628 memset(&ph->adds_features, 0, sizeof(ph->adds_features)); 629 perf_header__set_feat(ph, HEADER_BUILD_ID); 630 } 631 632 ph->event_offset = self->event_types.offset; 633 ph->event_size = self->event_types.size; 634 ph->data_offset = self->data.offset; 635 ph->data_size = self->data.size; 636 return 0; 637 } 638 639 static int perf_file_section__process(struct perf_file_section *self, 640 struct perf_header *ph, 641 int feat, int fd) 642 { 643 if (lseek(fd, self->offset, SEEK_SET) == (off_t)-1) { 644 pr_debug("Failed to lseek to %Ld offset for feature %d, " 645 "continuing...\n", self->offset, feat); 646 return 0; 647 } 648 649 switch (feat) { 650 case HEADER_TRACE_INFO: 651 trace_report(fd); 652 break; 653 654 case HEADER_BUILD_ID: 655 if (perf_header__read_build_ids(ph, fd, self->offset, self->size)) 656 pr_debug("Failed to read buildids, continuing...\n"); 657 break; 658 default: 659 pr_debug("unknown feature %d, continuing...\n", feat); 660 } 661 662 return 0; 663 } 664 665 int perf_header__read(struct perf_header *self, int fd) 666 { 667 struct perf_file_header f_header; 668 struct perf_file_attr f_attr; 669 u64 f_id; 670 int nr_attrs, nr_ids, i, j; 671 672 if (perf_file_header__read(&f_header, self, fd) < 0) { 673 pr_debug("incompatible file format\n"); 674 return -EINVAL; 675 } 676 677 nr_attrs = f_header.attrs.size / sizeof(f_attr); 678 lseek(fd, f_header.attrs.offset, SEEK_SET); 679 680 for (i = 0; i < nr_attrs; i++) { 681 struct perf_header_attr *attr; 682 off_t tmp; 683 684 if (perf_header__getbuffer64(self, fd, &f_attr, sizeof(f_attr))) 685 goto out_errno; 686 687 tmp = lseek(fd, 0, SEEK_CUR); 688 689 attr = perf_header_attr__new(&f_attr.attr); 690 if (attr == NULL) 691 return -ENOMEM; 692 693 nr_ids = f_attr.ids.size / sizeof(u64); 694 lseek(fd, f_attr.ids.offset, SEEK_SET); 695 696 for (j = 0; j < nr_ids; j++) { 697 if (perf_header__getbuffer64(self, fd, &f_id, sizeof(f_id))) 698 goto out_errno; 699 700 if (perf_header_attr__add_id(attr, f_id) < 0) { 701 perf_header_attr__delete(attr); 702 return -ENOMEM; 703 } 704 } 705 if (perf_header__add_attr(self, attr) < 0) { 706 perf_header_attr__delete(attr); 707 return -ENOMEM; 708 } 709 710 lseek(fd, tmp, SEEK_SET); 711 } 712 713 if (f_header.event_types.size) { 714 lseek(fd, f_header.event_types.offset, SEEK_SET); 715 events = malloc(f_header.event_types.size); 716 if (events == NULL) 717 return -ENOMEM; 718 if (perf_header__getbuffer64(self, fd, events, 719 f_header.event_types.size)) 720 goto out_errno; 721 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 722 } 723 724 perf_header__process_sections(self, fd, perf_file_section__process); 725 726 lseek(fd, self->data_offset, SEEK_SET); 727 728 self->frozen = 1; 729 return 0; 730 out_errno: 731 return -errno; 732 } 733 734 u64 perf_header__sample_type(struct perf_header *header) 735 { 736 u64 type = 0; 737 int i; 738 739 for (i = 0; i < header->attrs; i++) { 740 struct perf_header_attr *attr = header->attr[i]; 741 742 if (!type) 743 type = attr->attr.sample_type; 744 else if (type != attr->attr.sample_type) 745 die("non matching sample_type"); 746 } 747 748 return type; 749 } 750 751 struct perf_event_attr * 752 perf_header__find_attr(u64 id, struct perf_header *header) 753 { 754 int i; 755 756 for (i = 0; i < header->attrs; i++) { 757 struct perf_header_attr *attr = header->attr[i]; 758 int j; 759 760 for (j = 0; j < attr->ids; j++) { 761 if (attr->id[j] == id) 762 return &attr->attr; 763 } 764 } 765 766 return NULL; 767 } 768