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