aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-report.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r--tools/perf/builtin-report.c79
1 files changed, 35 insertions, 44 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index c1a54fc8527a..3ed3baf96ffb 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -349,22 +349,17 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm)
349 349
350 350
351static struct symbol * 351static struct symbol *
352resolve_symbol(struct thread *thread, struct map **mapp, 352resolve_symbol(struct thread *thread, struct map **mapp, u64 *ipp)
353 struct dso **dsop, u64 *ipp)
354{ 353{
355 struct dso *dso = dsop ? *dsop : NULL;
356 struct map *map = mapp ? *mapp : NULL; 354 struct map *map = mapp ? *mapp : NULL;
357 u64 ip = *ipp; 355 u64 ip = *ipp;
358 356
359 if (!thread)
360 return NULL;
361
362 if (dso)
363 goto got_dso;
364
365 if (map) 357 if (map)
366 goto got_map; 358 goto got_map;
367 359
360 if (!thread)
361 return NULL;
362
368 map = thread__find_map(thread, ip); 363 map = thread__find_map(thread, ip);
369 if (map != NULL) { 364 if (map != NULL) {
370 /* 365 /*
@@ -379,29 +374,29 @@ resolve_symbol(struct thread *thread, struct map **mapp,
379 *mapp = map; 374 *mapp = map;
380got_map: 375got_map:
381 ip = map->map_ip(map, ip); 376 ip = map->map_ip(map, ip);
382
383 dso = map->dso;
384 } else { 377 } else {
385 /* 378 /*
386 * If this is outside of all known maps, 379 * If this is outside of all known maps,
387 * and is a negative address, try to look it 380 * and is a negative address, try to look it
388 * up in the kernel dso, as it might be a 381 * up in the kernel dso, as it might be a
389 * vsyscall (which executes in user-mode): 382 * vsyscall or vdso (which executes in user-mode).
383 *
384 * XXX This is nasty, we should have a symbol list in
385 * the "[vdso]" dso, but for now lets use the old
386 * trick of looking in the whole kernel symbol list.
390 */ 387 */
391 if ((long long)ip < 0) 388 if ((long long)ip < 0) {
392 dso = kernel_dso; 389 map = kernel_map;
390 if (mapp)
391 *mapp = map;
392 }
393 } 393 }
394 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 394 dump_printf(" ...... dso: %s\n",
395 map ? map->dso->long_name : "<not found>");
395 dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip); 396 dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
396 *ipp = ip; 397 *ipp = ip;
397 398
398 if (dsop) 399 return map ? map->dso->find_symbol(map->dso, ip) : NULL;
399 *dsop = dso;
400
401 if (!dso)
402 return NULL;
403got_dso:
404 return dso->find_symbol(dso, ip);
405} 400}
406 401
407static int call__match(struct symbol *sym) 402static int call__match(struct symbol *sym)
@@ -413,7 +408,7 @@ static int call__match(struct symbol *sym)
413} 408}
414 409
415static struct symbol ** 410static struct symbol **
416resolve_callchain(struct thread *thread, struct map *map __used, 411resolve_callchain(struct thread *thread, struct map *map,
417 struct ip_callchain *chain, struct hist_entry *entry) 412 struct ip_callchain *chain, struct hist_entry *entry)
418{ 413{
419 u64 context = PERF_CONTEXT_MAX; 414 u64 context = PERF_CONTEXT_MAX;
@@ -430,8 +425,7 @@ resolve_callchain(struct thread *thread, struct map *map __used,
430 425
431 for (i = 0; i < chain->nr; i++) { 426 for (i = 0; i < chain->nr; i++) {
432 u64 ip = chain->ips[i]; 427 u64 ip = chain->ips[i];
433 struct dso *dso = NULL; 428 struct symbol *sym = NULL;
434 struct symbol *sym;
435 429
436 if (ip >= PERF_CONTEXT_MAX) { 430 if (ip >= PERF_CONTEXT_MAX) {
437 context = ip; 431 context = ip;
@@ -440,17 +434,15 @@ resolve_callchain(struct thread *thread, struct map *map __used,
440 434
441 switch (context) { 435 switch (context) {
442 case PERF_CONTEXT_HV: 436 case PERF_CONTEXT_HV:
443 dso = hypervisor_dso;
444 break; 437 break;
445 case PERF_CONTEXT_KERNEL: 438 case PERF_CONTEXT_KERNEL:
446 dso = kernel_dso; 439 sym = kernel_maps__find_symbol(ip, &map);
447 break; 440 break;
448 default: 441 default:
442 sym = resolve_symbol(thread, &map, &ip);
449 break; 443 break;
450 } 444 }
451 445
452 sym = resolve_symbol(thread, NULL, &dso, &ip);
453
454 if (sym) { 446 if (sym) {
455 if (sort__has_parent && call__match(sym) && 447 if (sort__has_parent && call__match(sym) &&
456 !entry->parent) 448 !entry->parent)
@@ -469,7 +461,7 @@ resolve_callchain(struct thread *thread, struct map *map __used,
469 */ 461 */
470 462
471static int 463static int
472hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 464hist_entry__add(struct thread *thread, struct map *map,
473 struct symbol *sym, u64 ip, struct ip_callchain *chain, 465 struct symbol *sym, u64 ip, struct ip_callchain *chain,
474 char level, u64 count) 466 char level, u64 count)
475{ 467{
@@ -480,7 +472,6 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
480 struct hist_entry entry = { 472 struct hist_entry entry = {
481 .thread = thread, 473 .thread = thread,
482 .map = map, 474 .map = map,
483 .dso = dso,
484 .sym = sym, 475 .sym = sym,
485 .ip = ip, 476 .ip = ip,
486 .level = level, 477 .level = level,
@@ -641,7 +632,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
641{ 632{
642 char level; 633 char level;
643 int show = 0; 634 int show = 0;
644 struct dso *dso = NULL; 635 struct symbol *sym = NULL;
645 struct thread *thread; 636 struct thread *thread;
646 u64 ip = event->ip.ip; 637 u64 ip = event->ip.ip;
647 u64 period = 1; 638 u64 period = 1;
@@ -700,35 +691,35 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
700 show = SHOW_KERNEL; 691 show = SHOW_KERNEL;
701 level = 'k'; 692 level = 'k';
702 693
703 dso = kernel_dso; 694 sym = kernel_maps__find_symbol(ip, &map);
704 695 dump_printf(" ...... dso: %s\n",
705 dump_printf(" ...... dso: %s\n", dso->name); 696 map ? map->dso->long_name : "<not found>");
706
707 } else if (cpumode == PERF_RECORD_MISC_USER) { 697 } else if (cpumode == PERF_RECORD_MISC_USER) {
708 698
709 show = SHOW_USER; 699 show = SHOW_USER;
710 level = '.'; 700 level = '.';
701 sym = resolve_symbol(thread, &map, &ip);
711 702
712 } else { 703 } else {
713 show = SHOW_HV; 704 show = SHOW_HV;
714 level = 'H'; 705 level = 'H';
715 706
716 dso = hypervisor_dso;
717
718 dump_printf(" ...... dso: [hypervisor]\n"); 707 dump_printf(" ...... dso: [hypervisor]\n");
719 } 708 }
720 709
721 if (show & show_mask) { 710 if (show & show_mask) {
722 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip); 711 if (dso_list &&
723 712 (!map || !map->dso ||
724 if (dso_list && (!dso || !dso->name || 713 !(strlist__has_entry(dso_list, map->dso->short_name) ||
725 !strlist__has_entry(dso_list, dso->name))) 714 (map->dso->short_name != map->dso->long_name &&
715 strlist__has_entry(dso_list, map->dso->long_name)))))
726 return 0; 716 return 0;
727 717
728 if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name))) 718 if (sym_list && sym && !strlist__has_entry(sym_list, sym->name))
729 return 0; 719 return 0;
730 720
731 if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) { 721 if (hist_entry__add(thread, map, sym, ip,
722 chain, level, period)) {
732 eprintf("problem incrementing symbol count, skipping event\n"); 723 eprintf("problem incrementing symbol count, skipping event\n");
733 return -1; 724 return -1;
734 } 725 }