1 #include <linux/types.h> 2 #include <sys/mman.h> 3 #include "event.h" 4 #include "debug.h" 5 #include "hist.h" 6 #include "machine.h" 7 #include "sort.h" 8 #include "string.h" 9 #include "strlist.h" 10 #include "thread.h" 11 #include "thread_map.h" 12 #include "symbol/kallsyms.h" 13 14 static const char *perf_event__names[] = { 15 [0] = "TOTAL", 16 [PERF_RECORD_MMAP] = "MMAP", 17 [PERF_RECORD_MMAP2] = "MMAP2", 18 [PERF_RECORD_LOST] = "LOST", 19 [PERF_RECORD_COMM] = "COMM", 20 [PERF_RECORD_EXIT] = "EXIT", 21 [PERF_RECORD_THROTTLE] = "THROTTLE", 22 [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE", 23 [PERF_RECORD_FORK] = "FORK", 24 [PERF_RECORD_READ] = "READ", 25 [PERF_RECORD_SAMPLE] = "SAMPLE", 26 [PERF_RECORD_HEADER_ATTR] = "ATTR", 27 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", 28 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", 29 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", 30 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", 31 }; 32 33 const char *perf_event__name(unsigned int id) 34 { 35 if (id >= ARRAY_SIZE(perf_event__names)) 36 return "INVALID"; 37 if (!perf_event__names[id]) 38 return "UNKNOWN"; 39 return perf_event__names[id]; 40 } 41 42 static struct perf_sample synth_sample = { 43 .pid = -1, 44 .tid = -1, 45 .time = -1, 46 .stream_id = -1, 47 .cpu = -1, 48 .period = 1, 49 }; 50 51 static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) 52 { 53 char filename[PATH_MAX]; 54 char bf[BUFSIZ]; 55 FILE *fp; 56 size_t size = 0; 57 pid_t tgid = -1; 58 59 snprintf(filename, sizeof(filename), "/proc/%d/status", pid); 60 61 fp = fopen(filename, "r"); 62 if (fp == NULL) { 63 pr_debug("couldn't open %s\n", filename); 64 return 0; 65 } 66 67 while (!comm[0] || (tgid < 0)) { 68 if (fgets(bf, sizeof(bf), fp) == NULL) { 69 pr_warning("couldn't get COMM and pgid, malformed %s\n", 70 filename); 71 break; 72 } 73 74 if (memcmp(bf, "Name:", 5) == 0) { 75 char *name = bf + 5; 76 while (*name && isspace(*name)) 77 ++name; 78 size = strlen(name) - 1; 79 if (size >= len) 80 size = len - 1; 81 memcpy(comm, name, size); 82 comm[size] = '\0'; 83 84 } else if (memcmp(bf, "Tgid:", 5) == 0) { 85 char *tgids = bf + 5; 86 while (*tgids && isspace(*tgids)) 87 ++tgids; 88 tgid = atoi(tgids); 89 } 90 } 91 92 fclose(fp); 93 94 return tgid; 95 } 96 97 static pid_t perf_event__synthesize_comm(struct perf_tool *tool, 98 union perf_event *event, pid_t pid, 99 perf_event__handler_t process, 100 struct machine *machine) 101 { 102 size_t size; 103 pid_t tgid; 104 105 memset(&event->comm, 0, sizeof(event->comm)); 106 107 if (machine__is_host(machine)) 108 tgid = perf_event__get_comm_tgid(pid, event->comm.comm, 109 sizeof(event->comm.comm)); 110 else 111 tgid = machine->pid; 112 113 if (tgid < 0) 114 goto out; 115 116 event->comm.pid = tgid; 117 event->comm.header.type = PERF_RECORD_COMM; 118 119 size = strlen(event->comm.comm) + 1; 120 size = PERF_ALIGN(size, sizeof(u64)); 121 memset(event->comm.comm + size, 0, machine->id_hdr_size); 122 event->comm.header.size = (sizeof(event->comm) - 123 (sizeof(event->comm.comm) - size) + 124 machine->id_hdr_size); 125 event->comm.tid = pid; 126 127 if (process(tool, event, &synth_sample, machine) != 0) 128 return -1; 129 130 out: 131 return tgid; 132 } 133 134 static int perf_event__synthesize_fork(struct perf_tool *tool, 135 union perf_event *event, pid_t pid, 136 pid_t tgid, perf_event__handler_t process, 137 struct machine *machine) 138 { 139 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); 140 141 /* this is really a clone event but we use fork to synthesize it */ 142 event->fork.ppid = tgid; 143 event->fork.ptid = tgid; 144 event->fork.pid = tgid; 145 event->fork.tid = pid; 146 event->fork.header.type = PERF_RECORD_FORK; 147 148 event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size); 149 150 if (process(tool, event, &synth_sample, machine) != 0) 151 return -1; 152 153 return 0; 154 } 155 156 int perf_event__synthesize_mmap_events(struct perf_tool *tool, 157 union perf_event *event, 158 pid_t pid, pid_t tgid, 159 perf_event__handler_t process, 160 struct machine *machine, 161 bool mmap_data) 162 { 163 char filename[PATH_MAX]; 164 FILE *fp; 165 int rc = 0; 166 167 if (machine__is_default_guest(machine)) 168 return 0; 169 170 snprintf(filename, sizeof(filename), "%s/proc/%d/maps", 171 machine->root_dir, pid); 172 173 fp = fopen(filename, "r"); 174 if (fp == NULL) { 175 /* 176 * We raced with a task exiting - just return: 177 */ 178 pr_debug("couldn't open %s\n", filename); 179 return -1; 180 } 181 182 event->header.type = PERF_RECORD_MMAP2; 183 184 while (1) { 185 char bf[BUFSIZ]; 186 char prot[5]; 187 char execname[PATH_MAX]; 188 char anonstr[] = "//anon"; 189 unsigned int ino; 190 size_t size; 191 ssize_t n; 192 193 if (fgets(bf, sizeof(bf), fp) == NULL) 194 break; 195 196 /* ensure null termination since stack will be reused. */ 197 strcpy(execname, ""); 198 199 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ 200 n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n", 201 &event->mmap2.start, &event->mmap2.len, prot, 202 &event->mmap2.pgoff, &event->mmap2.maj, 203 &event->mmap2.min, 204 &ino, execname); 205 206 /* 207 * Anon maps don't have the execname. 208 */ 209 if (n < 7) 210 continue; 211 212 event->mmap2.ino = (u64)ino; 213 214 /* 215 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c 216 */ 217 if (machine__is_host(machine)) 218 event->header.misc = PERF_RECORD_MISC_USER; 219 else 220 event->header.misc = PERF_RECORD_MISC_GUEST_USER; 221 222 /* map protection and flags bits */ 223 event->mmap2.prot = 0; 224 event->mmap2.flags = 0; 225 if (prot[0] == 'r') 226 event->mmap2.prot |= PROT_READ; 227 if (prot[1] == 'w') 228 event->mmap2.prot |= PROT_WRITE; 229 if (prot[2] == 'x') 230 event->mmap2.prot |= PROT_EXEC; 231 232 if (prot[3] == 's') 233 event->mmap2.flags |= MAP_SHARED; 234 else 235 event->mmap2.flags |= MAP_PRIVATE; 236 237 if (prot[2] != 'x') { 238 if (!mmap_data || prot[0] != 'r') 239 continue; 240 241 event->header.misc |= PERF_RECORD_MISC_MMAP_DATA; 242 } 243 244 if (!strcmp(execname, "")) 245 strcpy(execname, anonstr); 246 247 size = strlen(execname) + 1; 248 memcpy(event->mmap2.filename, execname, size); 249 size = PERF_ALIGN(size, sizeof(u64)); 250 event->mmap2.len -= event->mmap.start; 251 event->mmap2.header.size = (sizeof(event->mmap2) - 252 (sizeof(event->mmap2.filename) - size)); 253 memset(event->mmap2.filename + size, 0, machine->id_hdr_size); 254 event->mmap2.header.size += machine->id_hdr_size; 255 event->mmap2.pid = tgid; 256 event->mmap2.tid = pid; 257 258 if (process(tool, event, &synth_sample, machine) != 0) { 259 rc = -1; 260 break; 261 } 262 } 263 264 fclose(fp); 265 return rc; 266 } 267 268 int perf_event__synthesize_modules(struct perf_tool *tool, 269 perf_event__handler_t process, 270 struct machine *machine) 271 { 272 int rc = 0; 273 struct rb_node *nd; 274 struct map_groups *kmaps = &machine->kmaps; 275 union perf_event *event = zalloc((sizeof(event->mmap) + 276 machine->id_hdr_size)); 277 if (event == NULL) { 278 pr_debug("Not enough memory synthesizing mmap event " 279 "for kernel modules\n"); 280 return -1; 281 } 282 283 event->header.type = PERF_RECORD_MMAP; 284 285 /* 286 * kernel uses 0 for user space maps, see kernel/perf_event.c 287 * __perf_event_mmap 288 */ 289 if (machine__is_host(machine)) 290 event->header.misc = PERF_RECORD_MISC_KERNEL; 291 else 292 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 293 294 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); 295 nd; nd = rb_next(nd)) { 296 size_t size; 297 struct map *pos = rb_entry(nd, struct map, rb_node); 298 299 if (pos->dso->kernel) 300 continue; 301 302 size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 303 event->mmap.header.type = PERF_RECORD_MMAP; 304 event->mmap.header.size = (sizeof(event->mmap) - 305 (sizeof(event->mmap.filename) - size)); 306 memset(event->mmap.filename + size, 0, machine->id_hdr_size); 307 event->mmap.header.size += machine->id_hdr_size; 308 event->mmap.start = pos->start; 309 event->mmap.len = pos->end - pos->start; 310 event->mmap.pid = machine->pid; 311 312 memcpy(event->mmap.filename, pos->dso->long_name, 313 pos->dso->long_name_len + 1); 314 if (process(tool, event, &synth_sample, machine) != 0) { 315 rc = -1; 316 break; 317 } 318 } 319 320 free(event); 321 return rc; 322 } 323 324 static int __event__synthesize_thread(union perf_event *comm_event, 325 union perf_event *mmap_event, 326 union perf_event *fork_event, 327 pid_t pid, int full, 328 perf_event__handler_t process, 329 struct perf_tool *tool, 330 struct machine *machine, bool mmap_data) 331 { 332 char filename[PATH_MAX]; 333 DIR *tasks; 334 struct dirent dirent, *next; 335 pid_t tgid; 336 337 /* special case: only send one comm event using passed in pid */ 338 if (!full) { 339 tgid = perf_event__synthesize_comm(tool, comm_event, pid, 340 process, machine); 341 342 if (tgid == -1) 343 return -1; 344 345 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 346 process, machine, mmap_data); 347 } 348 349 if (machine__is_default_guest(machine)) 350 return 0; 351 352 snprintf(filename, sizeof(filename), "%s/proc/%d/task", 353 machine->root_dir, pid); 354 355 tasks = opendir(filename); 356 if (tasks == NULL) { 357 pr_debug("couldn't open %s\n", filename); 358 return 0; 359 } 360 361 while (!readdir_r(tasks, &dirent, &next) && next) { 362 char *end; 363 int rc = 0; 364 pid_t _pid; 365 366 _pid = strtol(dirent.d_name, &end, 10); 367 if (*end) 368 continue; 369 370 tgid = perf_event__synthesize_comm(tool, comm_event, _pid, 371 process, machine); 372 if (tgid == -1) 373 return -1; 374 375 if (_pid == pid) { 376 /* process the parent's maps too */ 377 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 378 process, machine, mmap_data); 379 } else { 380 /* only fork the tid's map, to save time */ 381 rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid, 382 process, machine); 383 } 384 385 if (rc) 386 return rc; 387 } 388 389 closedir(tasks); 390 return 0; 391 } 392 393 int perf_event__synthesize_thread_map(struct perf_tool *tool, 394 struct thread_map *threads, 395 perf_event__handler_t process, 396 struct machine *machine, 397 bool mmap_data) 398 { 399 union perf_event *comm_event, *mmap_event, *fork_event; 400 int err = -1, thread, j; 401 402 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size); 403 if (comm_event == NULL) 404 goto out; 405 406 mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size); 407 if (mmap_event == NULL) 408 goto out_free_comm; 409 410 fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size); 411 if (fork_event == NULL) 412 goto out_free_mmap; 413 414 err = 0; 415 for (thread = 0; thread < threads->nr; ++thread) { 416 if (__event__synthesize_thread(comm_event, mmap_event, 417 fork_event, 418 threads->map[thread], 0, 419 process, tool, machine, 420 mmap_data)) { 421 err = -1; 422 break; 423 } 424 425 /* 426 * comm.pid is set to thread group id by 427 * perf_event__synthesize_comm 428 */ 429 if ((int) comm_event->comm.pid != threads->map[thread]) { 430 bool need_leader = true; 431 432 /* is thread group leader in thread_map? */ 433 for (j = 0; j < threads->nr; ++j) { 434 if ((int) comm_event->comm.pid == threads->map[j]) { 435 need_leader = false; 436 break; 437 } 438 } 439 440 /* if not, generate events for it */ 441 if (need_leader && 442 __event__synthesize_thread(comm_event, mmap_event, 443 fork_event, 444 comm_event->comm.pid, 0, 445 process, tool, machine, 446 mmap_data)) { 447 err = -1; 448 break; 449 } 450 } 451 } 452 free(fork_event); 453 out_free_mmap: 454 free(mmap_event); 455 out_free_comm: 456 free(comm_event); 457 out: 458 return err; 459 } 460 461 int perf_event__synthesize_threads(struct perf_tool *tool, 462 perf_event__handler_t process, 463 struct machine *machine, bool mmap_data) 464 { 465 DIR *proc; 466 char proc_path[PATH_MAX]; 467 struct dirent dirent, *next; 468 union perf_event *comm_event, *mmap_event, *fork_event; 469 int err = -1; 470 471 if (machine__is_default_guest(machine)) 472 return 0; 473 474 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size); 475 if (comm_event == NULL) 476 goto out; 477 478 mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size); 479 if (mmap_event == NULL) 480 goto out_free_comm; 481 482 fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size); 483 if (fork_event == NULL) 484 goto out_free_mmap; 485 486 snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir); 487 proc = opendir(proc_path); 488 489 if (proc == NULL) 490 goto out_free_fork; 491 492 while (!readdir_r(proc, &dirent, &next) && next) { 493 char *end; 494 pid_t pid = strtol(dirent.d_name, &end, 10); 495 496 if (*end) /* only interested in proper numerical dirents */ 497 continue; 498 /* 499 * We may race with exiting thread, so don't stop just because 500 * one thread couldn't be synthesized. 501 */ 502 __event__synthesize_thread(comm_event, mmap_event, fork_event, pid, 503 1, process, tool, machine, mmap_data); 504 } 505 506 err = 0; 507 closedir(proc); 508 out_free_fork: 509 free(fork_event); 510 out_free_mmap: 511 free(mmap_event); 512 out_free_comm: 513 free(comm_event); 514 out: 515 return err; 516 } 517 518 struct process_symbol_args { 519 const char *name; 520 u64 start; 521 }; 522 523 static int find_symbol_cb(void *arg, const char *name, char type, 524 u64 start) 525 { 526 struct process_symbol_args *args = arg; 527 528 /* 529 * Must be a function or at least an alias, as in PARISC64, where "_text" is 530 * an 'A' to the same address as "_stext". 531 */ 532 if (!(symbol_type__is_a(type, MAP__FUNCTION) || 533 type == 'A') || strcmp(name, args->name)) 534 return 0; 535 536 args->start = start; 537 return 1; 538 } 539 540 u64 kallsyms__get_function_start(const char *kallsyms_filename, 541 const char *symbol_name) 542 { 543 struct process_symbol_args args = { .name = symbol_name, }; 544 545 if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0) 546 return 0; 547 548 return args.start; 549 } 550 551 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 552 perf_event__handler_t process, 553 struct machine *machine) 554 { 555 size_t size; 556 const char *mmap_name; 557 char name_buff[PATH_MAX]; 558 struct map *map; 559 struct kmap *kmap; 560 int err; 561 union perf_event *event; 562 563 if (machine->vmlinux_maps[0] == NULL) 564 return -1; 565 566 /* 567 * We should get this from /sys/kernel/sections/.text, but till that is 568 * available use this, and after it is use this as a fallback for older 569 * kernels. 570 */ 571 event = zalloc((sizeof(event->mmap) + machine->id_hdr_size)); 572 if (event == NULL) { 573 pr_debug("Not enough memory synthesizing mmap event " 574 "for kernel modules\n"); 575 return -1; 576 } 577 578 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); 579 if (machine__is_host(machine)) { 580 /* 581 * kernel uses PERF_RECORD_MISC_USER for user space maps, 582 * see kernel/perf_event.c __perf_event_mmap 583 */ 584 event->header.misc = PERF_RECORD_MISC_KERNEL; 585 } else { 586 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 587 } 588 589 map = machine->vmlinux_maps[MAP__FUNCTION]; 590 kmap = map__kmap(map); 591 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), 592 "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1; 593 size = PERF_ALIGN(size, sizeof(u64)); 594 event->mmap.header.type = PERF_RECORD_MMAP; 595 event->mmap.header.size = (sizeof(event->mmap) - 596 (sizeof(event->mmap.filename) - size) + machine->id_hdr_size); 597 event->mmap.pgoff = kmap->ref_reloc_sym->addr; 598 event->mmap.start = map->start; 599 event->mmap.len = map->end - event->mmap.start; 600 event->mmap.pid = machine->pid; 601 602 err = process(tool, event, &synth_sample, machine); 603 free(event); 604 605 return err; 606 } 607 608 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp) 609 { 610 const char *s; 611 612 if (event->header.misc & PERF_RECORD_MISC_COMM_EXEC) 613 s = " exec"; 614 else 615 s = ""; 616 617 return fprintf(fp, "%s: %s:%d\n", s, event->comm.comm, event->comm.tid); 618 } 619 620 int perf_event__process_comm(struct perf_tool *tool __maybe_unused, 621 union perf_event *event, 622 struct perf_sample *sample, 623 struct machine *machine) 624 { 625 return machine__process_comm_event(machine, event, sample); 626 } 627 628 int perf_event__process_lost(struct perf_tool *tool __maybe_unused, 629 union perf_event *event, 630 struct perf_sample *sample, 631 struct machine *machine) 632 { 633 return machine__process_lost_event(machine, event, sample); 634 } 635 636 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) 637 { 638 return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n", 639 event->mmap.pid, event->mmap.tid, event->mmap.start, 640 event->mmap.len, event->mmap.pgoff, 641 (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x', 642 event->mmap.filename); 643 } 644 645 size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp) 646 { 647 return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 648 " %02x:%02x %"PRIu64" %"PRIu64"]: %c%c%c%c %s\n", 649 event->mmap2.pid, event->mmap2.tid, event->mmap2.start, 650 event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj, 651 event->mmap2.min, event->mmap2.ino, 652 event->mmap2.ino_generation, 653 (event->mmap2.prot & PROT_READ) ? 'r' : '-', 654 (event->mmap2.prot & PROT_WRITE) ? 'w' : '-', 655 (event->mmap2.prot & PROT_EXEC) ? 'x' : '-', 656 (event->mmap2.flags & MAP_SHARED) ? 's' : 'p', 657 event->mmap2.filename); 658 } 659 660 int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, 661 union perf_event *event, 662 struct perf_sample *sample, 663 struct machine *machine) 664 { 665 return machine__process_mmap_event(machine, event, sample); 666 } 667 668 int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused, 669 union perf_event *event, 670 struct perf_sample *sample, 671 struct machine *machine) 672 { 673 return machine__process_mmap2_event(machine, event, sample); 674 } 675 676 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) 677 { 678 return fprintf(fp, "(%d:%d):(%d:%d)\n", 679 event->fork.pid, event->fork.tid, 680 event->fork.ppid, event->fork.ptid); 681 } 682 683 int perf_event__process_fork(struct perf_tool *tool __maybe_unused, 684 union perf_event *event, 685 struct perf_sample *sample, 686 struct machine *machine) 687 { 688 return machine__process_fork_event(machine, event, sample); 689 } 690 691 int perf_event__process_exit(struct perf_tool *tool __maybe_unused, 692 union perf_event *event, 693 struct perf_sample *sample, 694 struct machine *machine) 695 { 696 return machine__process_exit_event(machine, event, sample); 697 } 698 699 size_t perf_event__fprintf(union perf_event *event, FILE *fp) 700 { 701 size_t ret = fprintf(fp, "PERF_RECORD_%s", 702 perf_event__name(event->header.type)); 703 704 switch (event->header.type) { 705 case PERF_RECORD_COMM: 706 ret += perf_event__fprintf_comm(event, fp); 707 break; 708 case PERF_RECORD_FORK: 709 case PERF_RECORD_EXIT: 710 ret += perf_event__fprintf_task(event, fp); 711 break; 712 case PERF_RECORD_MMAP: 713 ret += perf_event__fprintf_mmap(event, fp); 714 break; 715 case PERF_RECORD_MMAP2: 716 ret += perf_event__fprintf_mmap2(event, fp); 717 break; 718 default: 719 ret += fprintf(fp, "\n"); 720 } 721 722 return ret; 723 } 724 725 int perf_event__process(struct perf_tool *tool __maybe_unused, 726 union perf_event *event, 727 struct perf_sample *sample, 728 struct machine *machine) 729 { 730 return machine__process_event(machine, event, sample); 731 } 732 733 void thread__find_addr_map(struct thread *thread, 734 struct machine *machine, u8 cpumode, 735 enum map_type type, u64 addr, 736 struct addr_location *al) 737 { 738 struct map_groups *mg = thread->mg; 739 bool load_map = false; 740 741 al->machine = machine; 742 al->thread = thread; 743 al->addr = addr; 744 al->cpumode = cpumode; 745 al->filtered = 0; 746 747 if (machine == NULL) { 748 al->map = NULL; 749 return; 750 } 751 752 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { 753 al->level = 'k'; 754 mg = &machine->kmaps; 755 load_map = true; 756 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { 757 al->level = '.'; 758 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { 759 al->level = 'g'; 760 mg = &machine->kmaps; 761 load_map = true; 762 } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) { 763 al->level = 'u'; 764 } else { 765 al->level = 'H'; 766 al->map = NULL; 767 768 if ((cpumode == PERF_RECORD_MISC_GUEST_USER || 769 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) && 770 !perf_guest) 771 al->filtered |= (1 << HIST_FILTER__GUEST); 772 if ((cpumode == PERF_RECORD_MISC_USER || 773 cpumode == PERF_RECORD_MISC_KERNEL) && 774 !perf_host) 775 al->filtered |= (1 << HIST_FILTER__HOST); 776 777 return; 778 } 779 try_again: 780 al->map = map_groups__find(mg, type, al->addr); 781 if (al->map == NULL) { 782 /* 783 * If this is outside of all known maps, and is a negative 784 * address, try to look it up in the kernel dso, as it might be 785 * a vsyscall or vdso (which executes in user-mode). 786 * 787 * XXX This is nasty, we should have a symbol list in the 788 * "[vdso]" dso, but for now lets use the old trick of looking 789 * in the whole kernel symbol list. 790 */ 791 if (cpumode == PERF_RECORD_MISC_USER && machine && 792 mg != &machine->kmaps && 793 machine__kernel_ip(machine, al->addr)) { 794 mg = &machine->kmaps; 795 load_map = true; 796 goto try_again; 797 } 798 } else { 799 /* 800 * Kernel maps might be changed when loading symbols so loading 801 * must be done prior to using kernel maps. 802 */ 803 if (load_map) 804 map__load(al->map, machine->symbol_filter); 805 al->addr = al->map->map_ip(al->map, al->addr); 806 } 807 } 808 809 void thread__find_addr_location(struct thread *thread, struct machine *machine, 810 u8 cpumode, enum map_type type, u64 addr, 811 struct addr_location *al) 812 { 813 thread__find_addr_map(thread, machine, cpumode, type, addr, al); 814 if (al->map != NULL) 815 al->sym = map__find_symbol(al->map, al->addr, 816 machine->symbol_filter); 817 else 818 al->sym = NULL; 819 } 820 821 int perf_event__preprocess_sample(const union perf_event *event, 822 struct machine *machine, 823 struct addr_location *al, 824 struct perf_sample *sample) 825 { 826 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 827 struct thread *thread = machine__findnew_thread(machine, sample->pid, 828 sample->tid); 829 830 if (thread == NULL) 831 return -1; 832 833 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); 834 /* 835 * Have we already created the kernel maps for this machine? 836 * 837 * This should have happened earlier, when we processed the kernel MMAP 838 * events, but for older perf.data files there was no such thing, so do 839 * it now. 840 */ 841 if (cpumode == PERF_RECORD_MISC_KERNEL && 842 machine->vmlinux_maps[MAP__FUNCTION] == NULL) 843 machine__create_kernel_maps(machine); 844 845 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 846 sample->ip, al); 847 dump_printf(" ...... dso: %s\n", 848 al->map ? al->map->dso->long_name : 849 al->level == 'H' ? "[hypervisor]" : "<not found>"); 850 851 if (thread__is_filtered(thread)) 852 al->filtered |= (1 << HIST_FILTER__THREAD); 853 854 al->sym = NULL; 855 al->cpu = sample->cpu; 856 857 if (al->map) { 858 struct dso *dso = al->map->dso; 859 860 if (symbol_conf.dso_list && 861 (!dso || !(strlist__has_entry(symbol_conf.dso_list, 862 dso->short_name) || 863 (dso->short_name != dso->long_name && 864 strlist__has_entry(symbol_conf.dso_list, 865 dso->long_name))))) { 866 al->filtered |= (1 << HIST_FILTER__DSO); 867 } 868 869 al->sym = map__find_symbol(al->map, al->addr, 870 machine->symbol_filter); 871 } 872 873 if (symbol_conf.sym_list && 874 (!al->sym || !strlist__has_entry(symbol_conf.sym_list, 875 al->sym->name))) { 876 al->filtered |= (1 << HIST_FILTER__SYMBOL); 877 } 878 879 return 0; 880 } 881 882 bool is_bts_event(struct perf_event_attr *attr) 883 { 884 return attr->type == PERF_TYPE_HARDWARE && 885 (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) && 886 attr->sample_period == 1; 887 } 888 889 bool sample_addr_correlates_sym(struct perf_event_attr *attr) 890 { 891 if (attr->type == PERF_TYPE_SOFTWARE && 892 (attr->config == PERF_COUNT_SW_PAGE_FAULTS || 893 attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN || 894 attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)) 895 return true; 896 897 if (is_bts_event(attr)) 898 return true; 899 900 return false; 901 } 902 903 void perf_event__preprocess_sample_addr(union perf_event *event, 904 struct perf_sample *sample, 905 struct machine *machine, 906 struct thread *thread, 907 struct addr_location *al) 908 { 909 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 910 911 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 912 sample->addr, al); 913 if (!al->map) 914 thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE, 915 sample->addr, al); 916 917 al->cpu = sample->cpu; 918 al->sym = NULL; 919 920 if (al->map) 921 al->sym = map__find_symbol(al->map, al->addr, NULL); 922 } 923