1 #include <linux/types.h> 2 #include "event.h" 3 #include "debug.h" 4 #include "session.h" 5 #include "sort.h" 6 #include "string.h" 7 #include "strlist.h" 8 #include "thread.h" 9 #include "thread_map.h" 10 11 static const char *perf_event__names[] = { 12 [0] = "TOTAL", 13 [PERF_RECORD_MMAP] = "MMAP", 14 [PERF_RECORD_LOST] = "LOST", 15 [PERF_RECORD_COMM] = "COMM", 16 [PERF_RECORD_EXIT] = "EXIT", 17 [PERF_RECORD_THROTTLE] = "THROTTLE", 18 [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE", 19 [PERF_RECORD_FORK] = "FORK", 20 [PERF_RECORD_READ] = "READ", 21 [PERF_RECORD_SAMPLE] = "SAMPLE", 22 [PERF_RECORD_HEADER_ATTR] = "ATTR", 23 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", 24 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", 25 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", 26 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", 27 }; 28 29 const char *perf_event__name(unsigned int id) 30 { 31 if (id >= ARRAY_SIZE(perf_event__names)) 32 return "INVALID"; 33 if (!perf_event__names[id]) 34 return "UNKNOWN"; 35 return perf_event__names[id]; 36 } 37 38 static struct perf_sample synth_sample = { 39 .pid = -1, 40 .tid = -1, 41 .time = -1, 42 .stream_id = -1, 43 .cpu = -1, 44 .period = 1, 45 }; 46 47 static pid_t perf_event__synthesize_comm(union perf_event *event, pid_t pid, 48 int full, perf_event__handler_t process, 49 struct perf_session *session) 50 { 51 char filename[PATH_MAX]; 52 char bf[BUFSIZ]; 53 FILE *fp; 54 size_t size = 0; 55 DIR *tasks; 56 struct dirent dirent, *next; 57 pid_t tgid = 0; 58 59 snprintf(filename, sizeof(filename), "/proc/%d/status", pid); 60 61 fp = fopen(filename, "r"); 62 if (fp == NULL) { 63 out_race: 64 /* 65 * We raced with a task exiting - just return: 66 */ 67 pr_debug("couldn't open %s\n", filename); 68 return 0; 69 } 70 71 memset(&event->comm, 0, sizeof(event->comm)); 72 73 while (!event->comm.comm[0] || !event->comm.pid) { 74 if (fgets(bf, sizeof(bf), fp) == NULL) { 75 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename); 76 goto out; 77 } 78 79 if (memcmp(bf, "Name:", 5) == 0) { 80 char *name = bf + 5; 81 while (*name && isspace(*name)) 82 ++name; 83 size = strlen(name) - 1; 84 memcpy(event->comm.comm, name, size++); 85 } else if (memcmp(bf, "Tgid:", 5) == 0) { 86 char *tgids = bf + 5; 87 while (*tgids && isspace(*tgids)) 88 ++tgids; 89 tgid = event->comm.pid = atoi(tgids); 90 } 91 } 92 93 event->comm.header.type = PERF_RECORD_COMM; 94 size = ALIGN(size, sizeof(u64)); 95 memset(event->comm.comm + size, 0, session->id_hdr_size); 96 event->comm.header.size = (sizeof(event->comm) - 97 (sizeof(event->comm.comm) - size) + 98 session->id_hdr_size); 99 if (!full) { 100 event->comm.tid = pid; 101 102 process(event, &synth_sample, session); 103 goto out; 104 } 105 106 snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 107 108 tasks = opendir(filename); 109 if (tasks == NULL) 110 goto out_race; 111 112 while (!readdir_r(tasks, &dirent, &next) && next) { 113 char *end; 114 pid = strtol(dirent.d_name, &end, 10); 115 if (*end) 116 continue; 117 118 event->comm.tid = pid; 119 120 process(event, &synth_sample, session); 121 } 122 123 closedir(tasks); 124 out: 125 fclose(fp); 126 127 return tgid; 128 } 129 130 static int perf_event__synthesize_mmap_events(union perf_event *event, 131 pid_t pid, pid_t tgid, 132 perf_event__handler_t process, 133 struct perf_session *session) 134 { 135 char filename[PATH_MAX]; 136 FILE *fp; 137 138 snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); 139 140 fp = fopen(filename, "r"); 141 if (fp == NULL) { 142 /* 143 * We raced with a task exiting - just return: 144 */ 145 pr_debug("couldn't open %s\n", filename); 146 return -1; 147 } 148 149 event->header.type = PERF_RECORD_MMAP; 150 /* 151 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c 152 */ 153 event->header.misc = PERF_RECORD_MISC_USER; 154 155 while (1) { 156 char bf[BUFSIZ], *pbf = bf; 157 int n; 158 size_t size; 159 if (fgets(bf, sizeof(bf), fp) == NULL) 160 break; 161 162 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ 163 n = hex2u64(pbf, &event->mmap.start); 164 if (n < 0) 165 continue; 166 pbf += n + 1; 167 n = hex2u64(pbf, &event->mmap.len); 168 if (n < 0) 169 continue; 170 pbf += n + 3; 171 if (*pbf == 'x') { /* vm_exec */ 172 char anonstr[] = "//anon\n"; 173 char *execname = strchr(bf, '/'); 174 175 /* Catch VDSO */ 176 if (execname == NULL) 177 execname = strstr(bf, "[vdso]"); 178 179 /* Catch anonymous mmaps */ 180 if ((execname == NULL) && !strstr(bf, "[")) 181 execname = anonstr; 182 183 if (execname == NULL) 184 continue; 185 186 pbf += 3; 187 n = hex2u64(pbf, &event->mmap.pgoff); 188 189 size = strlen(execname); 190 execname[size - 1] = '\0'; /* Remove \n */ 191 memcpy(event->mmap.filename, execname, size); 192 size = ALIGN(size, sizeof(u64)); 193 event->mmap.len -= event->mmap.start; 194 event->mmap.header.size = (sizeof(event->mmap) - 195 (sizeof(event->mmap.filename) - size)); 196 memset(event->mmap.filename + size, 0, session->id_hdr_size); 197 event->mmap.header.size += session->id_hdr_size; 198 event->mmap.pid = tgid; 199 event->mmap.tid = pid; 200 201 process(event, &synth_sample, session); 202 } 203 } 204 205 fclose(fp); 206 return 0; 207 } 208 209 int perf_event__synthesize_modules(perf_event__handler_t process, 210 struct perf_session *session, 211 struct machine *machine) 212 { 213 struct rb_node *nd; 214 struct map_groups *kmaps = &machine->kmaps; 215 union perf_event *event = zalloc((sizeof(event->mmap) + 216 session->id_hdr_size)); 217 if (event == NULL) { 218 pr_debug("Not enough memory synthesizing mmap event " 219 "for kernel modules\n"); 220 return -1; 221 } 222 223 event->header.type = PERF_RECORD_MMAP; 224 225 /* 226 * kernel uses 0 for user space maps, see kernel/perf_event.c 227 * __perf_event_mmap 228 */ 229 if (machine__is_host(machine)) 230 event->header.misc = PERF_RECORD_MISC_KERNEL; 231 else 232 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 233 234 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); 235 nd; nd = rb_next(nd)) { 236 size_t size; 237 struct map *pos = rb_entry(nd, struct map, rb_node); 238 239 if (pos->dso->kernel) 240 continue; 241 242 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 243 event->mmap.header.type = PERF_RECORD_MMAP; 244 event->mmap.header.size = (sizeof(event->mmap) - 245 (sizeof(event->mmap.filename) - size)); 246 memset(event->mmap.filename + size, 0, session->id_hdr_size); 247 event->mmap.header.size += session->id_hdr_size; 248 event->mmap.start = pos->start; 249 event->mmap.len = pos->end - pos->start; 250 event->mmap.pid = machine->pid; 251 252 memcpy(event->mmap.filename, pos->dso->long_name, 253 pos->dso->long_name_len + 1); 254 process(event, &synth_sample, session); 255 } 256 257 free(event); 258 return 0; 259 } 260 261 static int __event__synthesize_thread(union perf_event *comm_event, 262 union perf_event *mmap_event, 263 pid_t pid, perf_event__handler_t process, 264 struct perf_session *session) 265 { 266 pid_t tgid = perf_event__synthesize_comm(comm_event, pid, 1, process, 267 session); 268 if (tgid == -1) 269 return -1; 270 return perf_event__synthesize_mmap_events(mmap_event, pid, tgid, 271 process, session); 272 } 273 274 int perf_event__synthesize_thread_map(struct thread_map *threads, 275 perf_event__handler_t process, 276 struct perf_session *session) 277 { 278 union perf_event *comm_event, *mmap_event; 279 int err = -1, thread; 280 281 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 282 if (comm_event == NULL) 283 goto out; 284 285 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); 286 if (mmap_event == NULL) 287 goto out_free_comm; 288 289 err = 0; 290 for (thread = 0; thread < threads->nr; ++thread) { 291 if (__event__synthesize_thread(comm_event, mmap_event, 292 threads->map[thread], 293 process, session)) { 294 err = -1; 295 break; 296 } 297 } 298 free(mmap_event); 299 out_free_comm: 300 free(comm_event); 301 out: 302 return err; 303 } 304 305 int perf_event__synthesize_threads(perf_event__handler_t process, 306 struct perf_session *session) 307 { 308 DIR *proc; 309 struct dirent dirent, *next; 310 union perf_event *comm_event, *mmap_event; 311 int err = -1; 312 313 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 314 if (comm_event == NULL) 315 goto out; 316 317 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); 318 if (mmap_event == NULL) 319 goto out_free_comm; 320 321 proc = opendir("/proc"); 322 if (proc == NULL) 323 goto out_free_mmap; 324 325 while (!readdir_r(proc, &dirent, &next) && next) { 326 char *end; 327 pid_t pid = strtol(dirent.d_name, &end, 10); 328 329 if (*end) /* only interested in proper numerical dirents */ 330 continue; 331 332 __event__synthesize_thread(comm_event, mmap_event, pid, 333 process, session); 334 } 335 336 closedir(proc); 337 err = 0; 338 out_free_mmap: 339 free(mmap_event); 340 out_free_comm: 341 free(comm_event); 342 out: 343 return err; 344 } 345 346 struct process_symbol_args { 347 const char *name; 348 u64 start; 349 }; 350 351 static int find_symbol_cb(void *arg, const char *name, char type, 352 u64 start, u64 end __used) 353 { 354 struct process_symbol_args *args = arg; 355 356 /* 357 * Must be a function or at least an alias, as in PARISC64, where "_text" is 358 * an 'A' to the same address as "_stext". 359 */ 360 if (!(symbol_type__is_a(type, MAP__FUNCTION) || 361 type == 'A') || strcmp(name, args->name)) 362 return 0; 363 364 args->start = start; 365 return 1; 366 } 367 368 int perf_event__synthesize_kernel_mmap(perf_event__handler_t process, 369 struct perf_session *session, 370 struct machine *machine, 371 const char *symbol_name) 372 { 373 size_t size; 374 const char *filename, *mmap_name; 375 char path[PATH_MAX]; 376 char name_buff[PATH_MAX]; 377 struct map *map; 378 int err; 379 /* 380 * We should get this from /sys/kernel/sections/.text, but till that is 381 * available use this, and after it is use this as a fallback for older 382 * kernels. 383 */ 384 struct process_symbol_args args = { .name = symbol_name, }; 385 union perf_event *event = zalloc((sizeof(event->mmap) + 386 session->id_hdr_size)); 387 if (event == NULL) { 388 pr_debug("Not enough memory synthesizing mmap event " 389 "for kernel modules\n"); 390 return -1; 391 } 392 393 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); 394 if (machine__is_host(machine)) { 395 /* 396 * kernel uses PERF_RECORD_MISC_USER for user space maps, 397 * see kernel/perf_event.c __perf_event_mmap 398 */ 399 event->header.misc = PERF_RECORD_MISC_KERNEL; 400 filename = "/proc/kallsyms"; 401 } else { 402 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 403 if (machine__is_default_guest(machine)) 404 filename = (char *) symbol_conf.default_guest_kallsyms; 405 else { 406 sprintf(path, "%s/proc/kallsyms", machine->root_dir); 407 filename = path; 408 } 409 } 410 411 if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) 412 return -ENOENT; 413 414 map = machine->vmlinux_maps[MAP__FUNCTION]; 415 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), 416 "%s%s", mmap_name, symbol_name) + 1; 417 size = ALIGN(size, sizeof(u64)); 418 event->mmap.header.type = PERF_RECORD_MMAP; 419 event->mmap.header.size = (sizeof(event->mmap) - 420 (sizeof(event->mmap.filename) - size) + session->id_hdr_size); 421 event->mmap.pgoff = args.start; 422 event->mmap.start = map->start; 423 event->mmap.len = map->end - event->mmap.start; 424 event->mmap.pid = machine->pid; 425 426 err = process(event, &synth_sample, session); 427 free(event); 428 429 return err; 430 } 431 432 int perf_event__process_comm(union perf_event *event, 433 struct perf_sample *sample __used, 434 struct perf_session *session) 435 { 436 struct thread *thread = perf_session__findnew(session, event->comm.tid); 437 438 dump_printf(": %s:%d\n", event->comm.comm, event->comm.tid); 439 440 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { 441 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 442 return -1; 443 } 444 445 return 0; 446 } 447 448 int perf_event__process_lost(union perf_event *event, 449 struct perf_sample *sample __used, 450 struct perf_session *session) 451 { 452 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", 453 event->lost.id, event->lost.lost); 454 session->hists.stats.total_lost += event->lost.lost; 455 return 0; 456 } 457 458 static void perf_event__set_kernel_mmap_len(union perf_event *event, 459 struct map **maps) 460 { 461 maps[MAP__FUNCTION]->start = event->mmap.start; 462 maps[MAP__FUNCTION]->end = event->mmap.start + event->mmap.len; 463 /* 464 * Be a bit paranoid here, some perf.data file came with 465 * a zero sized synthesized MMAP event for the kernel. 466 */ 467 if (maps[MAP__FUNCTION]->end == 0) 468 maps[MAP__FUNCTION]->end = ~0ULL; 469 } 470 471 static int perf_event__process_kernel_mmap(union perf_event *event, 472 struct perf_session *session) 473 { 474 struct map *map; 475 char kmmap_prefix[PATH_MAX]; 476 struct machine *machine; 477 enum dso_kernel_type kernel_type; 478 bool is_kernel_mmap; 479 480 machine = perf_session__findnew_machine(session, event->mmap.pid); 481 if (!machine) { 482 pr_err("Can't find id %d's machine\n", event->mmap.pid); 483 goto out_problem; 484 } 485 486 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); 487 if (machine__is_host(machine)) 488 kernel_type = DSO_TYPE_KERNEL; 489 else 490 kernel_type = DSO_TYPE_GUEST_KERNEL; 491 492 is_kernel_mmap = memcmp(event->mmap.filename, 493 kmmap_prefix, 494 strlen(kmmap_prefix)) == 0; 495 if (event->mmap.filename[0] == '/' || 496 (!is_kernel_mmap && event->mmap.filename[0] == '[')) { 497 498 char short_module_name[1024]; 499 char *name, *dot; 500 501 if (event->mmap.filename[0] == '/') { 502 name = strrchr(event->mmap.filename, '/'); 503 if (name == NULL) 504 goto out_problem; 505 506 ++name; /* skip / */ 507 dot = strrchr(name, '.'); 508 if (dot == NULL) 509 goto out_problem; 510 snprintf(short_module_name, sizeof(short_module_name), 511 "[%.*s]", (int)(dot - name), name); 512 strxfrchar(short_module_name, '-', '_'); 513 } else 514 strcpy(short_module_name, event->mmap.filename); 515 516 map = machine__new_module(machine, event->mmap.start, 517 event->mmap.filename); 518 if (map == NULL) 519 goto out_problem; 520 521 name = strdup(short_module_name); 522 if (name == NULL) 523 goto out_problem; 524 525 map->dso->short_name = name; 526 map->dso->sname_alloc = 1; 527 map->end = map->start + event->mmap.len; 528 } else if (is_kernel_mmap) { 529 const char *symbol_name = (event->mmap.filename + 530 strlen(kmmap_prefix)); 531 /* 532 * Should be there already, from the build-id table in 533 * the header. 534 */ 535 struct dso *kernel = __dsos__findnew(&machine->kernel_dsos, 536 kmmap_prefix); 537 if (kernel == NULL) 538 goto out_problem; 539 540 kernel->kernel = kernel_type; 541 if (__machine__create_kernel_maps(machine, kernel) < 0) 542 goto out_problem; 543 544 perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps); 545 546 /* 547 * Avoid using a zero address (kptr_restrict) for the ref reloc 548 * symbol. Effectively having zero here means that at record 549 * time /proc/sys/kernel/kptr_restrict was non zero. 550 */ 551 if (event->mmap.pgoff != 0) { 552 perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, 553 symbol_name, 554 event->mmap.pgoff); 555 } 556 557 if (machine__is_default_guest(machine)) { 558 /* 559 * preload dso of guest kernel and modules 560 */ 561 dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION], 562 NULL); 563 } 564 } 565 return 0; 566 out_problem: 567 return -1; 568 } 569 570 int perf_event__process_mmap(union perf_event *event, 571 struct perf_sample *sample __used, 572 struct perf_session *session) 573 { 574 struct machine *machine; 575 struct thread *thread; 576 struct map *map; 577 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 578 int ret = 0; 579 580 dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", 581 event->mmap.pid, event->mmap.tid, event->mmap.start, 582 event->mmap.len, event->mmap.pgoff, event->mmap.filename); 583 584 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || 585 cpumode == PERF_RECORD_MISC_KERNEL) { 586 ret = perf_event__process_kernel_mmap(event, session); 587 if (ret < 0) 588 goto out_problem; 589 return 0; 590 } 591 592 machine = perf_session__find_host_machine(session); 593 if (machine == NULL) 594 goto out_problem; 595 thread = perf_session__findnew(session, event->mmap.pid); 596 if (thread == NULL) 597 goto out_problem; 598 map = map__new(&machine->user_dsos, event->mmap.start, 599 event->mmap.len, event->mmap.pgoff, 600 event->mmap.pid, event->mmap.filename, 601 MAP__FUNCTION); 602 if (map == NULL) 603 goto out_problem; 604 605 thread__insert_map(thread, map); 606 return 0; 607 608 out_problem: 609 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n"); 610 return 0; 611 } 612 613 int perf_event__process_task(union perf_event *event, 614 struct perf_sample *sample __used, 615 struct perf_session *session) 616 { 617 struct thread *thread = perf_session__findnew(session, event->fork.tid); 618 struct thread *parent = perf_session__findnew(session, event->fork.ptid); 619 620 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 621 event->fork.ppid, event->fork.ptid); 622 623 if (event->header.type == PERF_RECORD_EXIT) { 624 perf_session__remove_thread(session, thread); 625 return 0; 626 } 627 628 if (thread == NULL || parent == NULL || 629 thread__fork(thread, parent) < 0) { 630 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); 631 return -1; 632 } 633 634 return 0; 635 } 636 637 int perf_event__process(union perf_event *event, struct perf_sample *sample, 638 struct perf_session *session) 639 { 640 switch (event->header.type) { 641 case PERF_RECORD_COMM: 642 perf_event__process_comm(event, sample, session); 643 break; 644 case PERF_RECORD_MMAP: 645 perf_event__process_mmap(event, sample, session); 646 break; 647 case PERF_RECORD_FORK: 648 case PERF_RECORD_EXIT: 649 perf_event__process_task(event, sample, session); 650 break; 651 case PERF_RECORD_LOST: 652 perf_event__process_lost(event, sample, session); 653 default: 654 break; 655 } 656 657 return 0; 658 } 659 660 void thread__find_addr_map(struct thread *self, 661 struct perf_session *session, u8 cpumode, 662 enum map_type type, pid_t pid, u64 addr, 663 struct addr_location *al) 664 { 665 struct map_groups *mg = &self->mg; 666 struct machine *machine = NULL; 667 668 al->thread = self; 669 al->addr = addr; 670 al->cpumode = cpumode; 671 al->filtered = false; 672 673 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { 674 al->level = 'k'; 675 machine = perf_session__find_host_machine(session); 676 if (machine == NULL) { 677 al->map = NULL; 678 return; 679 } 680 mg = &machine->kmaps; 681 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { 682 al->level = '.'; 683 machine = perf_session__find_host_machine(session); 684 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { 685 al->level = 'g'; 686 machine = perf_session__find_machine(session, pid); 687 if (machine == NULL) { 688 al->map = NULL; 689 return; 690 } 691 mg = &machine->kmaps; 692 } else { 693 /* 694 * 'u' means guest os user space. 695 * TODO: We don't support guest user space. Might support late. 696 */ 697 if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) 698 al->level = 'u'; 699 else 700 al->level = 'H'; 701 al->map = NULL; 702 703 if ((cpumode == PERF_RECORD_MISC_GUEST_USER || 704 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) && 705 !perf_guest) 706 al->filtered = true; 707 if ((cpumode == PERF_RECORD_MISC_USER || 708 cpumode == PERF_RECORD_MISC_KERNEL) && 709 !perf_host) 710 al->filtered = true; 711 712 return; 713 } 714 try_again: 715 al->map = map_groups__find(mg, type, al->addr); 716 if (al->map == NULL) { 717 /* 718 * If this is outside of all known maps, and is a negative 719 * address, try to look it up in the kernel dso, as it might be 720 * a vsyscall or vdso (which executes in user-mode). 721 * 722 * XXX This is nasty, we should have a symbol list in the 723 * "[vdso]" dso, but for now lets use the old trick of looking 724 * in the whole kernel symbol list. 725 */ 726 if ((long long)al->addr < 0 && 727 cpumode == PERF_RECORD_MISC_USER && 728 machine && mg != &machine->kmaps) { 729 mg = &machine->kmaps; 730 goto try_again; 731 } 732 } else 733 al->addr = al->map->map_ip(al->map, al->addr); 734 } 735 736 void thread__find_addr_location(struct thread *self, 737 struct perf_session *session, u8 cpumode, 738 enum map_type type, pid_t pid, u64 addr, 739 struct addr_location *al, 740 symbol_filter_t filter) 741 { 742 thread__find_addr_map(self, session, cpumode, type, pid, addr, al); 743 if (al->map != NULL) 744 al->sym = map__find_symbol(al->map, al->addr, filter); 745 else 746 al->sym = NULL; 747 } 748 749 int perf_event__preprocess_sample(const union perf_event *event, 750 struct perf_session *session, 751 struct addr_location *al, 752 struct perf_sample *sample, 753 symbol_filter_t filter) 754 { 755 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 756 struct thread *thread = perf_session__findnew(session, event->ip.pid); 757 758 if (thread == NULL) 759 return -1; 760 761 if (symbol_conf.comm_list && 762 !strlist__has_entry(symbol_conf.comm_list, thread->comm)) 763 goto out_filtered; 764 765 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 766 /* 767 * Have we already created the kernel maps for the host machine? 768 * 769 * This should have happened earlier, when we processed the kernel MMAP 770 * events, but for older perf.data files there was no such thing, so do 771 * it now. 772 */ 773 if (cpumode == PERF_RECORD_MISC_KERNEL && 774 session->host_machine.vmlinux_maps[MAP__FUNCTION] == NULL) 775 machine__create_kernel_maps(&session->host_machine); 776 777 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 778 event->ip.pid, event->ip.ip, al); 779 dump_printf(" ...... dso: %s\n", 780 al->map ? al->map->dso->long_name : 781 al->level == 'H' ? "[hypervisor]" : "<not found>"); 782 al->sym = NULL; 783 al->cpu = sample->cpu; 784 785 if (al->map) { 786 if (symbol_conf.dso_list && 787 (!al->map || !al->map->dso || 788 !(strlist__has_entry(symbol_conf.dso_list, 789 al->map->dso->short_name) || 790 (al->map->dso->short_name != al->map->dso->long_name && 791 strlist__has_entry(symbol_conf.dso_list, 792 al->map->dso->long_name))))) 793 goto out_filtered; 794 795 al->sym = map__find_symbol(al->map, al->addr, filter); 796 } 797 798 if (symbol_conf.sym_list && al->sym && 799 !strlist__has_entry(symbol_conf.sym_list, al->sym->name)) 800 goto out_filtered; 801 802 return 0; 803 804 out_filtered: 805 al->filtered = true; 806 return 0; 807 } 808