lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 16 Aug 2017 18:18:34 +0800
From:   Jin Yao <yao.jin@...ux.intel.com>
To:     acme@...nel.org, jolsa@...nel.org, peterz@...radead.org,
        mingo@...hat.com, alexander.shishkin@...ux.intel.com
Cc:     Linux-kernel@...r.kernel.org, ak@...ux.intel.com,
        kan.liang@...el.com, yao.jin@...el.com,
        Jin Yao <yao.jin@...ux.intel.com>
Subject: [PATCH v1 2/4] perf annotate: Display multiple events for stdio mode

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.jin@...ux.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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ