1 #define _FILE_OFFSET_BITS 64 2 3 #include <linux/kernel.h> 4 5 #include <byteswap.h> 6 #include <unistd.h> 7 #include <sys/types.h> 8 #include <sys/mman.h> 9 10 #include "session.h" 11 #include "sort.h" 12 #include "util.h" 13 14 static int perf_session__open(struct perf_session *self, bool force) 15 { 16 struct stat input_stat; 17 18 if (!strcmp(self->filename, "-")) { 19 self->fd_pipe = true; 20 self->fd = STDIN_FILENO; 21 22 if (perf_header__read(self, self->fd) < 0) 23 pr_err("incompatible file format"); 24 25 return 0; 26 } 27 28 self->fd = open(self->filename, O_RDONLY); 29 if (self->fd < 0) { 30 int err = errno; 31 32 pr_err("failed to open %s: %s", self->filename, strerror(err)); 33 if (err == ENOENT && !strcmp(self->filename, "perf.data")) 34 pr_err(" (try 'perf record' first)"); 35 pr_err("\n"); 36 return -errno; 37 } 38 39 if (fstat(self->fd, &input_stat) < 0) 40 goto out_close; 41 42 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { 43 pr_err("file %s not owned by current user or root\n", 44 self->filename); 45 goto out_close; 46 } 47 48 if (!input_stat.st_size) { 49 pr_info("zero-sized file (%s), nothing to do!\n", 50 self->filename); 51 goto out_close; 52 } 53 54 if (perf_header__read(self, self->fd) < 0) { 55 pr_err("incompatible file format"); 56 goto out_close; 57 } 58 59 self->size = input_stat.st_size; 60 return 0; 61 62 out_close: 63 close(self->fd); 64 self->fd = -1; 65 return -1; 66 } 67 68 void perf_session__update_sample_type(struct perf_session *self) 69 { 70 self->sample_type = perf_header__sample_type(&self->header); 71 } 72 73 int perf_session__create_kernel_maps(struct perf_session *self) 74 { 75 int ret = machine__create_kernel_maps(&self->host_machine); 76 77 if (ret >= 0) 78 ret = machines__create_guest_kernel_maps(&self->machines); 79 return ret; 80 } 81 82 struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) 83 { 84 size_t len = filename ? strlen(filename) + 1 : 0; 85 struct perf_session *self = zalloc(sizeof(*self) + len); 86 87 if (self == NULL) 88 goto out; 89 90 if (perf_header__init(&self->header) < 0) 91 goto out_free; 92 93 memcpy(self->filename, filename, len); 94 self->threads = RB_ROOT; 95 INIT_LIST_HEAD(&self->dead_threads); 96 self->hists_tree = RB_ROOT; 97 self->last_match = NULL; 98 self->mmap_window = 32; 99 self->machines = RB_ROOT; 100 self->repipe = repipe; 101 INIT_LIST_HEAD(&self->ordered_samples.samples_head); 102 machine__init(&self->host_machine, "", HOST_KERNEL_ID); 103 104 if (mode == O_RDONLY) { 105 if (perf_session__open(self, force) < 0) 106 goto out_delete; 107 } else if (mode == O_WRONLY) { 108 /* 109 * In O_RDONLY mode this will be performed when reading the 110 * kernel MMAP event, in event__process_mmap(). 111 */ 112 if (perf_session__create_kernel_maps(self) < 0) 113 goto out_delete; 114 } 115 116 perf_session__update_sample_type(self); 117 out: 118 return self; 119 out_free: 120 free(self); 121 return NULL; 122 out_delete: 123 perf_session__delete(self); 124 return NULL; 125 } 126 127 static void perf_session__delete_dead_threads(struct perf_session *self) 128 { 129 struct thread *n, *t; 130 131 list_for_each_entry_safe(t, n, &self->dead_threads, node) { 132 list_del(&t->node); 133 thread__delete(t); 134 } 135 } 136 137 static void perf_session__delete_threads(struct perf_session *self) 138 { 139 struct rb_node *nd = rb_first(&self->threads); 140 141 while (nd) { 142 struct thread *t = rb_entry(nd, struct thread, rb_node); 143 144 rb_erase(&t->rb_node, &self->threads); 145 nd = rb_next(nd); 146 thread__delete(t); 147 } 148 } 149 150 void perf_session__delete(struct perf_session *self) 151 { 152 perf_header__exit(&self->header); 153 perf_session__delete_dead_threads(self); 154 perf_session__delete_threads(self); 155 machine__exit(&self->host_machine); 156 close(self->fd); 157 free(self); 158 } 159 160 void perf_session__remove_thread(struct perf_session *self, struct thread *th) 161 { 162 rb_erase(&th->rb_node, &self->threads); 163 /* 164 * We may have references to this thread, for instance in some hist_entry 165 * instances, so just move them to a separate list. 166 */ 167 list_add_tail(&th->node, &self->dead_threads); 168 } 169 170 static bool symbol__match_parent_regex(struct symbol *sym) 171 { 172 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0)) 173 return 1; 174 175 return 0; 176 } 177 178 struct map_symbol *perf_session__resolve_callchain(struct perf_session *self, 179 struct thread *thread, 180 struct ip_callchain *chain, 181 struct symbol **parent) 182 { 183 u8 cpumode = PERF_RECORD_MISC_USER; 184 unsigned int i; 185 struct map_symbol *syms = calloc(chain->nr, sizeof(*syms)); 186 187 if (!syms) 188 return NULL; 189 190 for (i = 0; i < chain->nr; i++) { 191 u64 ip = chain->ips[i]; 192 struct addr_location al; 193 194 if (ip >= PERF_CONTEXT_MAX) { 195 switch (ip) { 196 case PERF_CONTEXT_HV: 197 cpumode = PERF_RECORD_MISC_HYPERVISOR; break; 198 case PERF_CONTEXT_KERNEL: 199 cpumode = PERF_RECORD_MISC_KERNEL; break; 200 case PERF_CONTEXT_USER: 201 cpumode = PERF_RECORD_MISC_USER; break; 202 default: 203 break; 204 } 205 continue; 206 } 207 208 al.filtered = false; 209 thread__find_addr_location(thread, self, cpumode, 210 MAP__FUNCTION, thread->pid, ip, &al, NULL); 211 if (al.sym != NULL) { 212 if (sort__has_parent && !*parent && 213 symbol__match_parent_regex(al.sym)) 214 *parent = al.sym; 215 if (!symbol_conf.use_callchain) 216 break; 217 syms[i].map = al.map; 218 syms[i].sym = al.sym; 219 } 220 } 221 222 return syms; 223 } 224 225 static int process_event_stub(event_t *event __used, 226 struct perf_session *session __used) 227 { 228 dump_printf(": unhandled!\n"); 229 return 0; 230 } 231 232 static int process_finished_round_stub(event_t *event __used, 233 struct perf_session *session __used, 234 struct perf_event_ops *ops __used) 235 { 236 dump_printf(": unhandled!\n"); 237 return 0; 238 } 239 240 static int process_finished_round(event_t *event, 241 struct perf_session *session, 242 struct perf_event_ops *ops); 243 244 static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) 245 { 246 if (handler->sample == NULL) 247 handler->sample = process_event_stub; 248 if (handler->mmap == NULL) 249 handler->mmap = process_event_stub; 250 if (handler->comm == NULL) 251 handler->comm = process_event_stub; 252 if (handler->fork == NULL) 253 handler->fork = process_event_stub; 254 if (handler->exit == NULL) 255 handler->exit = process_event_stub; 256 if (handler->lost == NULL) 257 handler->lost = process_event_stub; 258 if (handler->read == NULL) 259 handler->read = process_event_stub; 260 if (handler->throttle == NULL) 261 handler->throttle = process_event_stub; 262 if (handler->unthrottle == NULL) 263 handler->unthrottle = process_event_stub; 264 if (handler->attr == NULL) 265 handler->attr = process_event_stub; 266 if (handler->event_type == NULL) 267 handler->event_type = process_event_stub; 268 if (handler->tracing_data == NULL) 269 handler->tracing_data = process_event_stub; 270 if (handler->build_id == NULL) 271 handler->build_id = process_event_stub; 272 if (handler->finished_round == NULL) { 273 if (handler->ordered_samples) 274 handler->finished_round = process_finished_round; 275 else 276 handler->finished_round = process_finished_round_stub; 277 } 278 } 279 280 void mem_bswap_64(void *src, int byte_size) 281 { 282 u64 *m = src; 283 284 while (byte_size > 0) { 285 *m = bswap_64(*m); 286 byte_size -= sizeof(u64); 287 ++m; 288 } 289 } 290 291 static void event__all64_swap(event_t *self) 292 { 293 struct perf_event_header *hdr = &self->header; 294 mem_bswap_64(hdr + 1, self->header.size - sizeof(*hdr)); 295 } 296 297 static void event__comm_swap(event_t *self) 298 { 299 self->comm.pid = bswap_32(self->comm.pid); 300 self->comm.tid = bswap_32(self->comm.tid); 301 } 302 303 static void event__mmap_swap(event_t *self) 304 { 305 self->mmap.pid = bswap_32(self->mmap.pid); 306 self->mmap.tid = bswap_32(self->mmap.tid); 307 self->mmap.start = bswap_64(self->mmap.start); 308 self->mmap.len = bswap_64(self->mmap.len); 309 self->mmap.pgoff = bswap_64(self->mmap.pgoff); 310 } 311 312 static void event__task_swap(event_t *self) 313 { 314 self->fork.pid = bswap_32(self->fork.pid); 315 self->fork.tid = bswap_32(self->fork.tid); 316 self->fork.ppid = bswap_32(self->fork.ppid); 317 self->fork.ptid = bswap_32(self->fork.ptid); 318 self->fork.time = bswap_64(self->fork.time); 319 } 320 321 static void event__read_swap(event_t *self) 322 { 323 self->read.pid = bswap_32(self->read.pid); 324 self->read.tid = bswap_32(self->read.tid); 325 self->read.value = bswap_64(self->read.value); 326 self->read.time_enabled = bswap_64(self->read.time_enabled); 327 self->read.time_running = bswap_64(self->read.time_running); 328 self->read.id = bswap_64(self->read.id); 329 } 330 331 static void event__attr_swap(event_t *self) 332 { 333 size_t size; 334 335 self->attr.attr.type = bswap_32(self->attr.attr.type); 336 self->attr.attr.size = bswap_32(self->attr.attr.size); 337 self->attr.attr.config = bswap_64(self->attr.attr.config); 338 self->attr.attr.sample_period = bswap_64(self->attr.attr.sample_period); 339 self->attr.attr.sample_type = bswap_64(self->attr.attr.sample_type); 340 self->attr.attr.read_format = bswap_64(self->attr.attr.read_format); 341 self->attr.attr.wakeup_events = bswap_32(self->attr.attr.wakeup_events); 342 self->attr.attr.bp_type = bswap_32(self->attr.attr.bp_type); 343 self->attr.attr.bp_addr = bswap_64(self->attr.attr.bp_addr); 344 self->attr.attr.bp_len = bswap_64(self->attr.attr.bp_len); 345 346 size = self->header.size; 347 size -= (void *)&self->attr.id - (void *)self; 348 mem_bswap_64(self->attr.id, size); 349 } 350 351 static void event__event_type_swap(event_t *self) 352 { 353 self->event_type.event_type.event_id = 354 bswap_64(self->event_type.event_type.event_id); 355 } 356 357 static void event__tracing_data_swap(event_t *self) 358 { 359 self->tracing_data.size = bswap_32(self->tracing_data.size); 360 } 361 362 typedef void (*event__swap_op)(event_t *self); 363 364 static event__swap_op event__swap_ops[] = { 365 [PERF_RECORD_MMAP] = event__mmap_swap, 366 [PERF_RECORD_COMM] = event__comm_swap, 367 [PERF_RECORD_FORK] = event__task_swap, 368 [PERF_RECORD_EXIT] = event__task_swap, 369 [PERF_RECORD_LOST] = event__all64_swap, 370 [PERF_RECORD_READ] = event__read_swap, 371 [PERF_RECORD_SAMPLE] = event__all64_swap, 372 [PERF_RECORD_HEADER_ATTR] = event__attr_swap, 373 [PERF_RECORD_HEADER_EVENT_TYPE] = event__event_type_swap, 374 [PERF_RECORD_HEADER_TRACING_DATA] = event__tracing_data_swap, 375 [PERF_RECORD_HEADER_BUILD_ID] = NULL, 376 [PERF_RECORD_HEADER_MAX] = NULL, 377 }; 378 379 struct sample_queue { 380 u64 timestamp; 381 struct sample_event *event; 382 struct list_head list; 383 }; 384 385 static void flush_sample_queue(struct perf_session *s, 386 struct perf_event_ops *ops) 387 { 388 struct list_head *head = &s->ordered_samples.samples_head; 389 u64 limit = s->ordered_samples.next_flush; 390 struct sample_queue *tmp, *iter; 391 392 if (!ops->ordered_samples || !limit) 393 return; 394 395 list_for_each_entry_safe(iter, tmp, head, list) { 396 if (iter->timestamp > limit) 397 return; 398 399 if (iter == s->ordered_samples.last_inserted) 400 s->ordered_samples.last_inserted = NULL; 401 402 ops->sample((event_t *)iter->event, s); 403 404 s->ordered_samples.last_flush = iter->timestamp; 405 list_del(&iter->list); 406 free(iter->event); 407 free(iter); 408 } 409 } 410 411 /* 412 * When perf record finishes a pass on every buffers, it records this pseudo 413 * event. 414 * We record the max timestamp t found in the pass n. 415 * Assuming these timestamps are monotonic across cpus, we know that if 416 * a buffer still has events with timestamps below t, they will be all 417 * available and then read in the pass n + 1. 418 * Hence when we start to read the pass n + 2, we can safely flush every 419 * events with timestamps below t. 420 * 421 * ============ PASS n ================= 422 * CPU 0 | CPU 1 423 * | 424 * cnt1 timestamps | cnt2 timestamps 425 * 1 | 2 426 * 2 | 3 427 * - | 4 <--- max recorded 428 * 429 * ============ PASS n + 1 ============== 430 * CPU 0 | CPU 1 431 * | 432 * cnt1 timestamps | cnt2 timestamps 433 * 3 | 5 434 * 4 | 6 435 * 5 | 7 <---- max recorded 436 * 437 * Flush every events below timestamp 4 438 * 439 * ============ PASS n + 2 ============== 440 * CPU 0 | CPU 1 441 * | 442 * cnt1 timestamps | cnt2 timestamps 443 * 6 | 8 444 * 7 | 9 445 * - | 10 446 * 447 * Flush every events below timestamp 7 448 * etc... 449 */ 450 static int process_finished_round(event_t *event __used, 451 struct perf_session *session, 452 struct perf_event_ops *ops) 453 { 454 flush_sample_queue(session, ops); 455 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp; 456 457 return 0; 458 } 459 460 static void __queue_sample_end(struct sample_queue *new, struct list_head *head) 461 { 462 struct sample_queue *iter; 463 464 list_for_each_entry_reverse(iter, head, list) { 465 if (iter->timestamp < new->timestamp) { 466 list_add(&new->list, &iter->list); 467 return; 468 } 469 } 470 471 list_add(&new->list, head); 472 } 473 474 static void __queue_sample_before(struct sample_queue *new, 475 struct sample_queue *iter, 476 struct list_head *head) 477 { 478 list_for_each_entry_continue_reverse(iter, head, list) { 479 if (iter->timestamp < new->timestamp) { 480 list_add(&new->list, &iter->list); 481 return; 482 } 483 } 484 485 list_add(&new->list, head); 486 } 487 488 static void __queue_sample_after(struct sample_queue *new, 489 struct sample_queue *iter, 490 struct list_head *head) 491 { 492 list_for_each_entry_continue(iter, head, list) { 493 if (iter->timestamp > new->timestamp) { 494 list_add_tail(&new->list, &iter->list); 495 return; 496 } 497 } 498 list_add_tail(&new->list, head); 499 } 500 501 /* The queue is ordered by time */ 502 static void __queue_sample_event(struct sample_queue *new, 503 struct perf_session *s) 504 { 505 struct sample_queue *last_inserted = s->ordered_samples.last_inserted; 506 struct list_head *head = &s->ordered_samples.samples_head; 507 508 509 if (!last_inserted) { 510 __queue_sample_end(new, head); 511 return; 512 } 513 514 /* 515 * Most of the time the current event has a timestamp 516 * very close to the last event inserted, unless we just switched 517 * to another event buffer. Having a sorting based on a list and 518 * on the last inserted event that is close to the current one is 519 * probably more efficient than an rbtree based sorting. 520 */ 521 if (last_inserted->timestamp >= new->timestamp) 522 __queue_sample_before(new, last_inserted, head); 523 else 524 __queue_sample_after(new, last_inserted, head); 525 } 526 527 static int queue_sample_event(event_t *event, struct sample_data *data, 528 struct perf_session *s) 529 { 530 u64 timestamp = data->time; 531 struct sample_queue *new; 532 533 534 if (timestamp < s->ordered_samples.last_flush) { 535 printf("Warning: Timestamp below last timeslice flush\n"); 536 return -EINVAL; 537 } 538 539 new = malloc(sizeof(*new)); 540 if (!new) 541 return -ENOMEM; 542 543 new->timestamp = timestamp; 544 545 new->event = malloc(event->header.size); 546 if (!new->event) { 547 free(new); 548 return -ENOMEM; 549 } 550 551 memcpy(new->event, event, event->header.size); 552 553 __queue_sample_event(new, s); 554 s->ordered_samples.last_inserted = new; 555 556 if (new->timestamp > s->ordered_samples.max_timestamp) 557 s->ordered_samples.max_timestamp = new->timestamp; 558 559 return 0; 560 } 561 562 static int perf_session__process_sample(event_t *event, struct perf_session *s, 563 struct perf_event_ops *ops) 564 { 565 struct sample_data data; 566 567 if (!ops->ordered_samples) 568 return ops->sample(event, s); 569 570 bzero(&data, sizeof(struct sample_data)); 571 event__parse_sample(event, s->sample_type, &data); 572 573 queue_sample_event(event, &data, s); 574 575 return 0; 576 } 577 578 static int perf_session__process_event(struct perf_session *self, 579 event_t *event, 580 struct perf_event_ops *ops, 581 u64 offset, u64 head) 582 { 583 trace_event(event); 584 585 if (event->header.type < PERF_RECORD_HEADER_MAX) { 586 dump_printf("%#Lx [%#x]: PERF_RECORD_%s", 587 offset + head, event->header.size, 588 event__name[event->header.type]); 589 hists__inc_nr_events(&self->hists, event->header.type); 590 } 591 592 if (self->header.needs_swap && event__swap_ops[event->header.type]) 593 event__swap_ops[event->header.type](event); 594 595 switch (event->header.type) { 596 case PERF_RECORD_SAMPLE: 597 return perf_session__process_sample(event, self, ops); 598 case PERF_RECORD_MMAP: 599 return ops->mmap(event, self); 600 case PERF_RECORD_COMM: 601 return ops->comm(event, self); 602 case PERF_RECORD_FORK: 603 return ops->fork(event, self); 604 case PERF_RECORD_EXIT: 605 return ops->exit(event, self); 606 case PERF_RECORD_LOST: 607 return ops->lost(event, self); 608 case PERF_RECORD_READ: 609 return ops->read(event, self); 610 case PERF_RECORD_THROTTLE: 611 return ops->throttle(event, self); 612 case PERF_RECORD_UNTHROTTLE: 613 return ops->unthrottle(event, self); 614 case PERF_RECORD_HEADER_ATTR: 615 return ops->attr(event, self); 616 case PERF_RECORD_HEADER_EVENT_TYPE: 617 return ops->event_type(event, self); 618 case PERF_RECORD_HEADER_TRACING_DATA: 619 /* setup for reading amidst mmap */ 620 lseek(self->fd, offset + head, SEEK_SET); 621 return ops->tracing_data(event, self); 622 case PERF_RECORD_HEADER_BUILD_ID: 623 return ops->build_id(event, self); 624 case PERF_RECORD_FINISHED_ROUND: 625 return ops->finished_round(event, self, ops); 626 default: 627 ++self->hists.stats.nr_unknown_events; 628 return -1; 629 } 630 } 631 632 void perf_event_header__bswap(struct perf_event_header *self) 633 { 634 self->type = bswap_32(self->type); 635 self->misc = bswap_16(self->misc); 636 self->size = bswap_16(self->size); 637 } 638 639 static struct thread *perf_session__register_idle_thread(struct perf_session *self) 640 { 641 struct thread *thread = perf_session__findnew(self, 0); 642 643 if (thread == NULL || thread__set_comm(thread, "swapper")) { 644 pr_err("problem inserting idle task.\n"); 645 thread = NULL; 646 } 647 648 return thread; 649 } 650 651 int do_read(int fd, void *buf, size_t size) 652 { 653 void *buf_start = buf; 654 655 while (size) { 656 int ret = read(fd, buf, size); 657 658 if (ret <= 0) 659 return ret; 660 661 size -= ret; 662 buf += ret; 663 } 664 665 return buf - buf_start; 666 } 667 668 #define session_done() (*(volatile int *)(&session_done)) 669 volatile int session_done; 670 671 static int __perf_session__process_pipe_events(struct perf_session *self, 672 struct perf_event_ops *ops) 673 { 674 event_t event; 675 uint32_t size; 676 int skip = 0; 677 u64 head; 678 int err; 679 void *p; 680 681 perf_event_ops__fill_defaults(ops); 682 683 head = 0; 684 more: 685 err = do_read(self->fd, &event, sizeof(struct perf_event_header)); 686 if (err <= 0) { 687 if (err == 0) 688 goto done; 689 690 pr_err("failed to read event header\n"); 691 goto out_err; 692 } 693 694 if (self->header.needs_swap) 695 perf_event_header__bswap(&event.header); 696 697 size = event.header.size; 698 if (size == 0) 699 size = 8; 700 701 p = &event; 702 p += sizeof(struct perf_event_header); 703 704 if (size - sizeof(struct perf_event_header)) { 705 err = do_read(self->fd, p, 706 size - sizeof(struct perf_event_header)); 707 if (err <= 0) { 708 if (err == 0) { 709 pr_err("unexpected end of event stream\n"); 710 goto done; 711 } 712 713 pr_err("failed to read event data\n"); 714 goto out_err; 715 } 716 } 717 718 if (size == 0 || 719 (skip = perf_session__process_event(self, &event, ops, 720 0, head)) < 0) { 721 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n", 722 head, event.header.size, event.header.type); 723 /* 724 * assume we lost track of the stream, check alignment, and 725 * increment a single u64 in the hope to catch on again 'soon'. 726 */ 727 if (unlikely(head & 7)) 728 head &= ~7ULL; 729 730 size = 8; 731 } 732 733 head += size; 734 735 dump_printf("\n%#Lx [%#x]: event: %d\n", 736 head, event.header.size, event.header.type); 737 738 if (skip > 0) 739 head += skip; 740 741 if (!session_done()) 742 goto more; 743 done: 744 err = 0; 745 out_err: 746 return err; 747 } 748 749 int __perf_session__process_events(struct perf_session *self, 750 u64 data_offset, u64 data_size, 751 u64 file_size, struct perf_event_ops *ops) 752 { 753 int err, mmap_prot, mmap_flags; 754 u64 head, shift; 755 u64 offset = 0; 756 size_t page_size; 757 event_t *event; 758 uint32_t size; 759 char *buf; 760 struct ui_progress *progress = ui_progress__new("Processing events...", 761 self->size); 762 if (progress == NULL) 763 return -1; 764 765 perf_event_ops__fill_defaults(ops); 766 767 page_size = sysconf(_SC_PAGESIZE); 768 769 head = data_offset; 770 shift = page_size * (head / page_size); 771 offset += shift; 772 head -= shift; 773 774 mmap_prot = PROT_READ; 775 mmap_flags = MAP_SHARED; 776 777 if (self->header.needs_swap) { 778 mmap_prot |= PROT_WRITE; 779 mmap_flags = MAP_PRIVATE; 780 } 781 remap: 782 buf = mmap(NULL, page_size * self->mmap_window, mmap_prot, 783 mmap_flags, self->fd, offset); 784 if (buf == MAP_FAILED) { 785 pr_err("failed to mmap file\n"); 786 err = -errno; 787 goto out_err; 788 } 789 790 more: 791 event = (event_t *)(buf + head); 792 ui_progress__update(progress, offset); 793 794 if (self->header.needs_swap) 795 perf_event_header__bswap(&event->header); 796 size = event->header.size; 797 if (size == 0) 798 size = 8; 799 800 if (head + event->header.size >= page_size * self->mmap_window) { 801 int munmap_ret; 802 803 shift = page_size * (head / page_size); 804 805 munmap_ret = munmap(buf, page_size * self->mmap_window); 806 assert(munmap_ret == 0); 807 808 offset += shift; 809 head -= shift; 810 goto remap; 811 } 812 813 size = event->header.size; 814 815 dump_printf("\n%#Lx [%#x]: event: %d\n", 816 offset + head, event->header.size, event->header.type); 817 818 if (size == 0 || 819 perf_session__process_event(self, event, ops, offset, head) < 0) { 820 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n", 821 offset + head, event->header.size, 822 event->header.type); 823 /* 824 * assume we lost track of the stream, check alignment, and 825 * increment a single u64 in the hope to catch on again 'soon'. 826 */ 827 if (unlikely(head & 7)) 828 head &= ~7ULL; 829 830 size = 8; 831 } 832 833 head += size; 834 835 if (offset + head >= data_offset + data_size) 836 goto done; 837 838 if (offset + head < file_size) 839 goto more; 840 done: 841 err = 0; 842 /* do the final flush for ordered samples */ 843 self->ordered_samples.next_flush = ULLONG_MAX; 844 flush_sample_queue(self, ops); 845 out_err: 846 ui_progress__delete(progress); 847 return err; 848 } 849 850 int perf_session__process_events(struct perf_session *self, 851 struct perf_event_ops *ops) 852 { 853 int err; 854 855 if (perf_session__register_idle_thread(self) == NULL) 856 return -ENOMEM; 857 858 if (!self->fd_pipe) 859 err = __perf_session__process_events(self, 860 self->header.data_offset, 861 self->header.data_size, 862 self->size, ops); 863 else 864 err = __perf_session__process_pipe_events(self, ops); 865 866 return err; 867 } 868 869 bool perf_session__has_traces(struct perf_session *self, const char *msg) 870 { 871 if (!(self->sample_type & PERF_SAMPLE_RAW)) { 872 pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg); 873 return false; 874 } 875 876 return true; 877 } 878 879 int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps, 880 const char *symbol_name, 881 u64 addr) 882 { 883 char *bracket; 884 enum map_type i; 885 struct ref_reloc_sym *ref; 886 887 ref = zalloc(sizeof(struct ref_reloc_sym)); 888 if (ref == NULL) 889 return -ENOMEM; 890 891 ref->name = strdup(symbol_name); 892 if (ref->name == NULL) { 893 free(ref); 894 return -ENOMEM; 895 } 896 897 bracket = strchr(ref->name, ']'); 898 if (bracket) 899 *bracket = '\0'; 900 901 ref->addr = addr; 902 903 for (i = 0; i < MAP__NR_TYPES; ++i) { 904 struct kmap *kmap = map__kmap(maps[i]); 905 kmap->ref_reloc_sym = ref; 906 } 907 908 return 0; 909 } 910 911 size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) 912 { 913 return __dsos__fprintf(&self->host_machine.kernel_dsos, fp) + 914 __dsos__fprintf(&self->host_machine.user_dsos, fp) + 915 machines__fprintf_dsos(&self->machines, fp); 916 } 917 918 size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, 919 bool with_hits) 920 { 921 size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits); 922 return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits); 923 } 924