|
20 | 20 | #include "util/evlist.h"
|
21 | 21 | #include "util/evsel.h"
|
22 | 22 | #include "util/annotate.h"
|
| 23 | +#include "util/annotate-data.h" |
23 | 24 | #include "util/event.h"
|
24 | 25 | #include <subcmd/parse-options.h>
|
25 | 26 | #include "util/parse-events.h"
|
@@ -55,9 +56,11 @@ struct perf_annotate {
|
55 | 56 | bool skip_missing;
|
56 | 57 | bool has_br_stack;
|
57 | 58 | bool group_set;
|
| 59 | + bool data_type; |
58 | 60 | float min_percent;
|
59 | 61 | const char *sym_hist_filter;
|
60 | 62 | const char *cpu_list;
|
| 63 | + const char *target_data_type; |
61 | 64 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
|
62 | 65 | };
|
63 | 66 |
|
@@ -322,6 +325,32 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
|
322 | 325 | return symbol__tty_annotate2(&he->ms, evsel);
|
323 | 326 | }
|
324 | 327 |
|
| 328 | +static void print_annotated_data_type(struct annotated_data_type *mem_type, |
| 329 | + struct annotated_member *member, |
| 330 | + struct evsel *evsel, int indent) |
| 331 | +{ |
| 332 | + struct annotated_member *child; |
| 333 | + struct type_hist *h = mem_type->histograms[evsel->core.idx]; |
| 334 | + int i, samples = 0; |
| 335 | + |
| 336 | + for (i = 0; i < member->size; i++) |
| 337 | + samples += h->addr[member->offset + i].nr_samples; |
| 338 | + |
| 339 | + printf(" %10d %10d %10d %*s%s\t%s", |
| 340 | + samples, member->offset, member->size, indent, "", member->type_name, |
| 341 | + member->var_name ?: ""); |
| 342 | + |
| 343 | + if (!list_empty(&member->children)) |
| 344 | + printf(" {\n"); |
| 345 | + |
| 346 | + list_for_each_entry(child, &member->children, node) |
| 347 | + print_annotated_data_type(mem_type, child, evsel, indent + 4); |
| 348 | + |
| 349 | + if (!list_empty(&member->children)) |
| 350 | + printf("%*s}", 35 + indent, ""); |
| 351 | + printf(";\n"); |
| 352 | +} |
| 353 | + |
325 | 354 | static void hists__find_annotations(struct hists *hists,
|
326 | 355 | struct evsel *evsel,
|
327 | 356 | struct perf_annotate *ann)
|
@@ -361,6 +390,40 @@ static void hists__find_annotations(struct hists *hists,
|
361 | 390 | continue;
|
362 | 391 | }
|
363 | 392 |
|
| 393 | + if (ann->data_type) { |
| 394 | + struct dso *dso = map__dso(he->ms.map); |
| 395 | + |
| 396 | + /* skip unknown type */ |
| 397 | + if (he->mem_type->histograms == NULL) |
| 398 | + goto find_next; |
| 399 | + |
| 400 | + if (ann->target_data_type) { |
| 401 | + const char *type_name = he->mem_type->self.type_name; |
| 402 | + |
| 403 | + /* skip 'struct ' prefix in the type name */ |
| 404 | + if (strncmp(ann->target_data_type, "struct ", 7) && |
| 405 | + !strncmp(type_name, "struct ", 7)) |
| 406 | + type_name += 7; |
| 407 | + |
| 408 | + /* skip 'union ' prefix in the type name */ |
| 409 | + if (strncmp(ann->target_data_type, "union ", 6) && |
| 410 | + !strncmp(type_name, "union ", 6)) |
| 411 | + type_name += 6; |
| 412 | + |
| 413 | + if (strcmp(ann->target_data_type, type_name)) |
| 414 | + goto find_next; |
| 415 | + } |
| 416 | + |
| 417 | + printf("Annotate type: '%s' in %s (%d samples):\n", |
| 418 | + he->mem_type->self.type_name, dso->name, he->stat.nr_events); |
| 419 | + printf("============================================================================\n"); |
| 420 | + printf(" %10s %10s %10s %s\n", "samples", "offset", "size", "field"); |
| 421 | + |
| 422 | + print_annotated_data_type(he->mem_type, &he->mem_type->self, evsel, 0); |
| 423 | + printf("\n"); |
| 424 | + goto find_next; |
| 425 | + } |
| 426 | + |
364 | 427 | if (use_browser == 2) {
|
365 | 428 | int ret;
|
366 | 429 | int (*annotate)(struct hist_entry *he,
|
@@ -496,6 +559,17 @@ static int parse_percent_limit(const struct option *opt, const char *str,
|
496 | 559 | return 0;
|
497 | 560 | }
|
498 | 561 |
|
| 562 | +static int parse_data_type(const struct option *opt, const char *str, int unset) |
| 563 | +{ |
| 564 | + struct perf_annotate *ann = opt->value; |
| 565 | + |
| 566 | + ann->data_type = !unset; |
| 567 | + if (str) |
| 568 | + ann->target_data_type = strdup(str); |
| 569 | + |
| 570 | + return 0; |
| 571 | +} |
| 572 | + |
499 | 573 | static const char * const annotate_usage[] = {
|
500 | 574 | "perf annotate [<options>]",
|
501 | 575 | NULL
|
@@ -607,6 +681,9 @@ int cmd_annotate(int argc, const char **argv)
|
607 | 681 | OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
|
608 | 682 | "Instruction Tracing options\n" ITRACE_HELP,
|
609 | 683 | itrace_parse_synth_opts),
|
| 684 | + OPT_CALLBACK_OPTARG(0, "data-type", &annotate, NULL, "name", |
| 685 | + "Show data type annotate for the memory accesses", |
| 686 | + parse_data_type), |
610 | 687 |
|
611 | 688 | OPT_END()
|
612 | 689 | };
|
@@ -661,6 +738,13 @@ int cmd_annotate(int argc, const char **argv)
|
661 | 738 | }
|
662 | 739 | #endif
|
663 | 740 |
|
| 741 | +#ifndef HAVE_DWARF_GETLOCATIONS_SUPPORT |
| 742 | + if (annotate.data_type) { |
| 743 | + pr_err("Error: Data type profiling is disabled due to missing DWARF support\n"); |
| 744 | + return -ENOTSUP; |
| 745 | + } |
| 746 | +#endif |
| 747 | + |
664 | 748 | ret = symbol__validate_sym_arguments();
|
665 | 749 | if (ret)
|
666 | 750 | return ret;
|
@@ -703,14 +787,25 @@ int cmd_annotate(int argc, const char **argv)
|
703 | 787 | use_browser = 2;
|
704 | 788 | #endif
|
705 | 789 |
|
| 790 | + /* FIXME: only support stdio for now */ |
| 791 | + if (annotate.data_type) { |
| 792 | + use_browser = 0; |
| 793 | + annotate_opts.annotate_src = false; |
| 794 | + symbol_conf.annotate_data_member = true; |
| 795 | + symbol_conf.annotate_data_sample = true; |
| 796 | + } |
| 797 | + |
706 | 798 | setup_browser(true);
|
707 | 799 |
|
708 | 800 | /*
|
709 | 801 | * Events of different processes may correspond to the same
|
710 | 802 | * symbol, we do not care about the processes in annotate,
|
711 | 803 | * set sort order to avoid repeated output.
|
712 | 804 | */
|
713 |
| - sort_order = "dso,symbol"; |
| 805 | + if (annotate.data_type) |
| 806 | + sort_order = "dso,type"; |
| 807 | + else |
| 808 | + sort_order = "dso,symbol"; |
714 | 809 |
|
715 | 810 | /*
|
716 | 811 | * Set SORT_MODE__BRANCH so that annotate display IPC/Cycle
|
|
0 commit comments