For example:
    perf record -e cycles,branches ./div
    perf annotate main --stdio

 Percent         |      Source code & Disassembly of div for branches,cycles 
(90966 samples)
--------------------------------------------------------------------------------------------
    ......
                 :              for (i = 0; i < 2000000000; i++) {
                 :                      flag = compute_flag();
    5.77    4.85 :        4004e8:       xor    %eax,%eax
    0.01    0.01 :        4004ea:       callq  400640 <compute_flag>
                 :
                 :                      count++;
    2.38    4.38 :        4004ef:       mov    0x200b57(%rip),%edx
    0.00    0.00 :        4004f5:       add    $0x1,%edx
                 :
                 :                      if (flag)
    0.00    0.00 :        4004f8:       test   %eax,%eax
                 :              srand(s_randseed);
                 :
                 :              for (i = 0; i < 2000000000; i++) {
                 :                      flag = compute_flag();
                 :
                 :                      count++;
    0.60    0.44 :        4004fa:       mov    %edx,0x200b4c(%rip)
                 :
                 :                      if (flag)
    3.99    4.32 :        400500:       je     400532 <main+0x82>

Signed-off-by: Jin Yao <yao....@linux.intel.com>
---
 tools/perf/builtin-annotate.c |   2 +-
 tools/perf/builtin-top.c      |   3 +-
 tools/perf/util/annotate.c    | 179 ++++++++++++++++++++++++++++++++----------
 tools/perf/util/annotate.h    |   6 +-
 4 files changed, 145 insertions(+), 45 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 833866c..98663bd 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -240,7 +240,7 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
                                    struct perf_annotate *ann)
 {
        return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel,
-                                   ann->print_line, ann->full_paths, 0, 0);
+                                   ann->print_line, ann->full_paths, 0, 0, he);
 }
 
 static void hists__find_annotations(struct hists *hists,
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index ee954bd..2287667 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -245,7 +245,8 @@ static void perf_top__show_details(struct perf_top *top)
        printf("  Events  Pcnt (>=%d%%)\n", top->sym_pcnt_filter);
 
        more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel,
-                                      0, top->sym_pcnt_filter, 
top->print_entries, 4);
+                                      0, top->sym_pcnt_filter,
+                                      top->print_entries, 4, NULL);
 
        if (top->evlist->enabled) {
                if (top->zero)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 16ec881..8630108 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1071,7 +1071,8 @@ static void annotate__branch_printf(struct block_range 
*br, u64 addr)
 
 static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 
start,
                      struct perf_evsel *evsel, u64 len, int min_pcnt, int 
printed,
-                     int max_lines, struct disasm_line *queue)
+                     int max_lines, struct disasm_line *queue,
+                     struct hist_entry *he)
 {
        static const char *prev_line;
        static const char *prev_color;
@@ -1082,31 +1083,39 @@ static int disasm_line__print(struct disasm_line *dl, 
struct symbol *sym, u64 st
                double *ppercents = &percent;
                struct sym_hist_entry sample;
                struct sym_hist_entry *psamples = &sample;
-               int i, nr_percent = 1;
+               int i, nr_percent;
                const char *color;
                struct annotation *notes = symbol__annotation(sym);
                s64 offset = dl->offset;
                const u64 addr = start + offset;
                struct disasm_line *next;
                struct block_range *br;
+               struct hist_event *hevt;
 
                next = disasm__get_next_ip_line(&notes->src->source, dl);
-
-               if (perf_evsel__is_group_event(evsel)) {
-                       nr_percent = evsel->nr_members;
-                       ppercents = calloc(nr_percent, sizeof(double));
-                       psamples = calloc(nr_percent, sizeof(struct 
sym_hist_entry));
-                       if (ppercents == NULL || psamples == NULL) {
-                               return -1;
-                       }
+               nr_percent = (evsel) ? 1 : he->event_nr;
+               ppercents = calloc(nr_percent, sizeof(double));
+               psamples = calloc(nr_percent, sizeof(struct sym_hist_entry));
+               if (ppercents == NULL || psamples == NULL) {
+                       return -1;
                }
 
                for (i = 0; i < nr_percent; i++) {
-                       percent = disasm__calc_percent(notes,
+                       if (evsel) {
+                               percent = disasm__calc_percent(notes,
                                        notes->src->lines ? i : evsel->idx + i,
                                        offset,
                                        next ? next->offset : (s64) len,
                                        &path, &sample);
+                       } else {
+                               hevt = &he->events[i];
+                               notes = symbol__annotation(hevt->ms.sym);
+                               percent = disasm__calc_percent(notes,
+                                       hevt->idx,
+                                       offset,
+                                       next ? next->offset : (s64) len,
+                                       &path, &sample);
+                       }
 
                        ppercents[i] = percent;
                        psamples[i] = sample;
@@ -1125,7 +1134,7 @@ static int disasm_line__print(struct disasm_line *dl, 
struct symbol *sym, u64 st
                                if (queue == dl)
                                        break;
                                disasm_line__print(queue, sym, start, evsel, 
len,
-                                                   0, 0, 1, NULL);
+                                                   0, 0, 1, NULL, he);
                        }
                }
 
@@ -1179,7 +1188,9 @@ static int disasm_line__print(struct disasm_line *dl, 
struct symbol *sym, u64 st
                if (queue)
                        return -1;
 
-               if (perf_evsel__is_group_event(evsel))
+               if (!evsel)
+                       width *= he->event_nr;
+               else if (perf_evsel__is_group_event(evsel))
                        width *= evsel->nr_members;
 
                if (!*dl->line)
@@ -1682,25 +1693,32 @@ static void symbol__free_source_line(struct symbol 
*sym, int len)
 /* Get the filename:line for the colored entries */
 static int symbol__get_source_line(struct symbol *sym, struct map *map,
                                   struct perf_evsel *evsel,
-                                  struct rb_root *root, int len)
+                                  struct rb_root *root, int len,
+                                  struct hist_entry *he)
 {
        u64 start;
        int i, k;
-       int evidx = evsel->idx;
        struct source_line *src_line;
        struct annotation *notes = symbol__annotation(sym);
-       struct sym_hist *h = annotation__histogram(notes, evidx);
+       struct sym_hist *h;
        struct rb_root tmp_root = RB_ROOT;
        int nr_pcnt = 1;
-       u64 nr_samples = h->nr_samples;
+       u64 nr_samples = 0;
        size_t sizeof_src_line = sizeof(struct source_line);
+       struct hist_event *hevt;
 
-       if (perf_evsel__is_group_event(evsel)) {
-               for (i = 1; i < evsel->nr_members; i++) {
-                       h = annotation__histogram(notes, evidx + i);
+       if (evsel) {
+               h = annotation__histogram(notes, evsel->idx);
+               nr_samples = h->nr_samples;
+       } else {
+               for (i = 0; i < he->event_nr; i++) {
+                       hevt = &he->events[i];
+                       notes = symbol__annotation(hevt->ms.sym);
+                       h = annotation__histogram(notes, hevt->idx);
                        nr_samples += h->nr_samples;
                }
-               nr_pcnt = evsel->nr_members;
+
+               nr_pcnt = he->event_nr;
                sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples);
        }
 
@@ -1722,7 +1740,15 @@ static int symbol__get_source_line(struct symbol *sym, 
struct map *map,
                for (k = 0; k < nr_pcnt; k++) {
                        double percent = 0.0;
 
-                       h = annotation__histogram(notes, evidx + k);
+                       if (evsel) {
+                               h = annotation__histogram(notes,
+                                                         evsel->idx + k);
+                       } else {
+                               hevt = &he->events[k];
+                               notes = symbol__annotation(hevt->ms.sym);
+                               h = annotation__histogram(notes, hevt->idx);
+                       }
+
                        nr_samples = h->addr[i].nr_samples;
                        if (h->nr_samples)
                                percent = 100.0 * nr_samples / h->nr_samples;
@@ -1787,29 +1813,67 @@ static void print_summary(struct rb_root *root, const 
char *filename)
        }
 }
 
-static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
+static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel,
+                                 struct hist_entry *he)
 {
        struct annotation *notes = symbol__annotation(sym);
-       struct sym_hist *h = annotation__histogram(notes, evsel->idx);
+       struct sym_hist *h;
        u64 len = symbol__size(sym), offset;
+       int i;
+       struct hist_event *hevt;
 
-       for (offset = 0; offset < len; ++offset)
-               if (h->addr[offset].nr_samples != 0)
-                       printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
-                              sym->start + offset, h->addr[offset].nr_samples);
-       printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->nr_samples", 
h->nr_samples);
+       for (offset = 0; offset < len; ++offset) {
+               if (evsel) {
+                       h = annotation__histogram(notes, evsel->idx);
+
+                       if (h->addr[offset].nr_samples != 0) {
+                               printf("%*" PRIx64 ": %" PRIu64 "\n",
+                                       BITS_PER_LONG / 2,
+                                       sym->start + offset,
+                                       h->addr[offset].nr_samples);
+                       }
+               } else {
+                       for (i = 0; i < he->event_nr; i++) {
+                               hevt = &he->events[i];
+                               notes = symbol__annotation(hevt->ms.sym);
+                               h = annotation__histogram(notes, hevt->idx);
+
+                               if (h->addr[offset].nr_samples != 0) {
+                                       printf("%*" PRIx64 ": %" PRIu64 "\n",
+                                               BITS_PER_LONG / 2,
+                                               sym->start + offset,
+                                               h->addr[offset].nr_samples);
+                               }
+                       }
+               }
+       }
+
+       if (evsel) {
+               h = annotation__histogram(notes, evsel->idx);
+               printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2,
+                       "h->nr_samples", h->nr_samples);
+       } else {
+               for (i = 0; i < he->event_nr; i++) {
+                       hevt = &he->events[i];
+                       notes = symbol__annotation(hevt->ms.sym);
+                       h = annotation__histogram(notes, hevt->idx);
+
+                       printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2,
+                               "h->nr_samples", h->nr_samples);
+               }
+       }
 }
 
 int symbol__annotate_printf(struct symbol *sym, struct map *map,
                            struct perf_evsel *evsel, bool full_paths,
-                           int min_pcnt, int max_lines, int context)
+                           int min_pcnt, int max_lines, int context,
+                           struct hist_entry *he)
 {
        struct dso *dso = map->dso;
        char *filename;
        const char *d_filename;
-       const char *evsel_name = perf_evsel__name(evsel);
        struct annotation *notes = symbol__annotation(sym);
-       struct sym_hist *h = annotation__histogram(notes, evsel->idx);
+       struct sym_hist *h;
        struct disasm_line *pos, *queue = NULL;
        u64 start = map__rip_2objdump(map, sym->start);
        int printed = 2, queue_len = 0;
@@ -1817,6 +1881,30 @@ int symbol__annotate_printf(struct symbol *sym, struct 
map *map,
        u64 len;
        int width = symbol_conf.show_total_period ? 12 : 8;
        int graph_dotted_len;
+       char name_buf[128];
+       int i, name_printed = 0;
+       u64 nr_samples = 0;
+       struct hist_event *hevt;
+
+       if (evsel) {
+               strncpy(name_buf, perf_evsel__name(evsel), sizeof(name_buf));
+               h = annotation__histogram(notes, evsel->idx);
+               nr_samples = h->nr_samples;
+
+       } else {
+               for (i = 0; i < he->event_nr; i++) {
+                       hevt = &he->events[i];
+                       name_printed += scnprintf(name_buf + name_printed,
+                               sizeof(name_buf) - name_printed,
+                               "%s%s",
+                               perf_evsel__name(hevt->evsel),
+                               (i < he->event_nr - 1) ? "," : "");
+
+                       notes = symbol__annotation(hevt->ms.sym);
+                       h = annotation__histogram(notes, hevt->idx);
+                       nr_samples += h->nr_samples;
+               }
+       }
 
        filename = strdup(dso->long_name);
        if (!filename)
@@ -1829,18 +1917,20 @@ int symbol__annotate_printf(struct symbol *sym, struct 
map *map,
 
        len = symbol__size(sym);
 
-       if (perf_evsel__is_group_event(evsel))
+       if (!evsel)
+               width *= he->event_nr;
+       else if (perf_evsel__is_group_event(evsel))
                width *= evsel->nr_members;
 
        graph_dotted_len = printf(" %-*.*s|     Source code & Disassembly of %s 
for %s (%" PRIu64 " samples)\n",
                                  width, width, symbol_conf.show_total_period ? 
"Event count" : "Percent",
-                                 d_filename, evsel_name, h->nr_samples);
+                                 d_filename, name_buf, nr_samples);
 
        printf("%-*.*s----\n",
               graph_dotted_len, graph_dotted_len, graph_dotted_line);
 
        if (verbose > 0)
-               symbol__annotate_hits(sym, evsel);
+               symbol__annotate_hits(sym, evsel, he);
 
        list_for_each_entry(pos, &notes->src->source, node) {
                if (context && queue == NULL) {
@@ -1850,7 +1940,7 @@ int symbol__annotate_printf(struct symbol *sym, struct 
map *map,
 
                switch (disasm_line__print(pos, sym, start, evsel, len,
                                            min_pcnt, printed, max_lines,
-                                           queue)) {
+                                           queue, he)) {
                case 0:
                        ++printed;
                        if (context) {
@@ -1945,26 +2035,33 @@ size_t disasm__fprintf(struct list_head *head, FILE *fp)
 
 int symbol__tty_annotate(struct symbol *sym, struct map *map,
                         struct perf_evsel *evsel, bool print_lines,
-                        bool full_paths, int min_pcnt, int max_lines)
+                        bool full_paths, int min_pcnt, int max_lines,
+                        struct hist_entry *he)
 {
        struct dso *dso = map->dso;
        struct rb_root source_line = RB_ROOT;
        u64 len;
+       char *arch;
 
-       if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
+       if (!evsel)
+               arch = perf_evsel__env_arch(he->events[0].evsel);
+       else
+               arch = perf_evsel__env_arch(evsel);
+
+       if (symbol__disassemble(sym, map, arch,
                                0, NULL, NULL) < 0)
                return -1;
-
        len = symbol__size(sym);
 
        if (print_lines) {
                srcline_full_filename = full_paths;
-               symbol__get_source_line(sym, map, evsel, &source_line, len);
+               symbol__get_source_line(sym, map, evsel, &source_line, len, he);
                print_summary(&source_line, dso->long_name);
        }
 
        symbol__annotate_printf(sym, map, evsel, full_paths,
-                               min_pcnt, max_lines, 0);
+                               min_pcnt, max_lines, 0, he);
+
        if (print_lines)
                symbol__free_source_line(sym, len);
 
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 0d44cfe..83b78ff 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -198,7 +198,8 @@ int symbol__strerror_disassemble(struct symbol *sym, struct 
map *map,
 
 int symbol__annotate_printf(struct symbol *sym, struct map *map,
                            struct perf_evsel *evsel, bool full_paths,
-                           int min_pcnt, int max_lines, int context);
+                           int min_pcnt, int max_lines, int context,
+                           struct hist_entry *he);
 void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
 void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
 void disasm__purge(struct list_head *head);
@@ -207,7 +208,8 @@ bool ui__has_annotation(void);
 
 int symbol__tty_annotate(struct symbol *sym, struct map *map,
                         struct perf_evsel *evsel, bool print_lines,
-                        bool full_paths, int min_pcnt, int max_lines);
+                        bool full_paths, int min_pcnt, int max_lines,
+                        struct hist_entry *he);
 
 #ifdef HAVE_SLANG_SUPPORT
 int symbol__tui_annotate(struct symbol *sym, struct map *map,
-- 
2.7.4

Reply via email to