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