* [PATCH v3 1/7] perf annotate: Use build-id dir when reading link name
2017-03-09 17:35 [PATCH v3 0/7] perf annotate: Fixes & Introduce --source-only and new source code view Taeung Song
@ 2017-03-09 17:35 ` Taeung Song
2017-03-09 17:35 ` [PATCH v3 2/7] perf annotate: Avoid division by zero when calculating percent Taeung Song
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Taeung Song @ 2017-03-09 17:35 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar,
Peter Zijlstra, Wang Nan, Masami Hiramatsu, Taeung Song,
Jiri Olsa
In dso__disassemble_filename() when reading link name
from a build-id file, it is failed each time
because a build-id file gotten from dso__build_id_filename()
is not symbolic link.
So use build-id directory path instead of a build-id file name.
For example, if build-id file name gotten from
dso__build_id_filename() is as below,
/root/.debug/.build-id/4f/75c7d197c951659d1c1b8b5fd49bcdf8f3f8b1/elf
instead of the above build-id file name,
use the build-id dir path that is a symbolic link as below.
/root/.debug/.build-id/4f/75c7d197c951659d1c1b8b5fd49bcdf8f3f8b1
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/util/annotate.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 273f21f..fc91c6b 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1307,6 +1307,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
{
char linkname[PATH_MAX];
char *build_id_filename;
+ char *build_id_path = NULL;
if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
!dso__is_kcore(dso))
@@ -1322,8 +1323,14 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
goto fallback;
}
+ build_id_path = strdup(filename);
+ if (!build_id_path)
+ return -1;
+
+ dirname(build_id_path);
+
if (dso__is_kcore(dso) ||
- readlink(filename, linkname, sizeof(linkname)) < 0 ||
+ readlink(build_id_path, linkname, sizeof(linkname)) < 0 ||
strstr(linkname, DSO__NAME_KALLSYMS) ||
access(filename, R_OK)) {
fallback:
@@ -1335,6 +1342,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
__symbol__join_symfs(filename, filename_size, dso->long_name);
}
+ free(build_id_path);
return 0;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 2/7] perf annotate: Avoid division by zero when calculating percent
2017-03-09 17:35 [PATCH v3 0/7] perf annotate: Fixes & Introduce --source-only and new source code view Taeung Song
2017-03-09 17:35 ` [PATCH v3 1/7] perf annotate: Use build-id dir when reading link name Taeung Song
@ 2017-03-09 17:35 ` Taeung Song
2017-03-09 17:35 ` [PATCH v3 3/7] perf annotate: Fix missing setting nr samples on source_line Taeung Song
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Taeung Song @ 2017-03-09 17:35 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar,
Peter Zijlstra, Wang Nan, Masami Hiramatsu, Taeung Song,
Jiri Olsa
Currently perf-annotate with --print-line can print
-nan(0x8000000000000) because of division by zero
when calculating percent.
So if a sum of samples is zero, skip calculating percent.
Before:
$ perf annotate --stdio -l
Sorted summary for file /home/taeung/workspace/a.out
----------------------------------------------
32.89 -nan 7.04 a.c:38
25.14 -nan 0.00 a.c:34
16.26 -nan 56.34 a.c:31
15.88 -nan 1.41 a.c:37
5.67 -nan 0.00 a.c:39
1.13 -nan 35.21 a.c:26
0.95 -nan 0.00 a.c:44
0.57 -nan 0.00 a.c:32
Percent | Source code & Disassembly of a.out for cycles (529 samples)
-----------------------------------------------------------------------------------------
:
...
a.c:26 0.57 -nan 4.23 : 40081a: mov %edi,-0x24(%rbp)
a.c:26 0.00 -nan 9.86 : 40081d: mov %rsi,-0x30(%rbp)
...
After:
$ perf annotate --stdio -l
Sorted summary for file /home/taeung/workspace/a.out
----------------------------------------------
32.89 0.00 7.04 a.c:38
25.14 0.00 0.00 a.c:34
16.26 0.00 56.34 a.c:31
15.88 0.00 1.41 a.c:37
5.67 0.00 0.00 a.c:39
1.13 0.00 35.21 a.c:26
0.95 0.00 0.00 a.c:44
0.57 0.00 0.00 a.c:32
Percent | Source code & Disassembly of old for cycles (529 samples)
-----------------------------------------------------------------------------------------
:
...
a.c:26 0.57 0.00 4.23 : 40081a: mov %edi,-0x24(%rbp)
a.c:26 0.00 0.00 9.86 : 40081d: mov %rsi,-0x30(%rbp)
...
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/util/annotate.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index fc91c6b..9bb43cd 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1665,11 +1665,15 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
src_line->nr_pcnt = nr_pcnt;
for (k = 0; k < nr_pcnt; k++) {
+ double percent = 0.0;
+
h = annotation__histogram(notes, evidx + k);
- src_line->samples[k].percent = 100.0 * h->addr[i] / h->sum;
+ if (h->sum)
+ percent = 100.0 * h->addr[i] / h->sum;
- if (src_line->samples[k].percent > percent_max)
- percent_max = src_line->samples[k].percent;
+ if (percent > percent_max)
+ percent_max = percent;
+ src_line->samples[k].percent = percent;
}
if (percent_max <= 0.5)
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 3/7] perf annotate: Fix missing setting nr samples on source_line
2017-03-09 17:35 [PATCH v3 0/7] perf annotate: Fixes & Introduce --source-only and new source code view Taeung Song
2017-03-09 17:35 ` [PATCH v3 1/7] perf annotate: Use build-id dir when reading link name Taeung Song
2017-03-09 17:35 ` [PATCH v3 2/7] perf annotate: Avoid division by zero when calculating percent Taeung Song
@ 2017-03-09 17:35 ` Taeung Song
2017-03-09 17:35 ` [PATCH v3 4/7] perf annotate: More exactly grep -v in symbol__disassemble() Taeung Song
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Taeung Song @ 2017-03-09 17:35 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar,
Peter Zijlstra, Wang Nan, Masami Hiramatsu, Taeung Song,
Jiri Olsa
If using --show-total-period with -l,
disasm__calc_percent() use a 'samples' array of source_line.
But samples[evidx].nr is always zero so print 0 values as below.
Before:
$ perf annotate --stdio -l --show-total-period
...
0 : 400816: push %rbp
0 : 400817: mov %rsp,%rbp
0 : 40081a: mov %edi,-0x24(%rbp)
0 : 40081d: mov %rsi,-0x30(%rbp)
0 : 400821: mov -0x24(%rbp),%eax
0 : 400824: mov -0x30(%rbp),%rdx
0 : 400828: mov (%rdx),%esi
0 : 40082a: mov $0x0,%edx
...
The reason is that in symbol__get_source_line() did't set
number of samples into a memeber variable 'nr' of samples
of source_line.
So fix it for correct number of samples
when using --show-total-period option as below.
After:
$ perf annotate --stdio -l --show-total-period
...
3 : 400816: push %rbp
4 : 400817: mov %rsp,%rbp
0 : 40081a: mov %edi,-0x24(%rbp)
0 : 40081d: mov %rsi,-0x30(%rbp)
1 : 400821: mov -0x24(%rbp),%eax
2 : 400824: mov -0x30(%rbp),%rdx
0 : 400828: mov (%rdx),%esi
1 : 40082a: mov $0x0,%edx
...
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/util/annotate.c | 6 ++++--
tools/perf/util/annotate.h | 2 +-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 9bb43cd..63130ec 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1659,7 +1659,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
start = map__rip_2objdump(map, sym->start);
for (i = 0; i < len; i++) {
- u64 offset;
+ u64 offset, nr_samples;
double percent_max = 0.0;
src_line->nr_pcnt = nr_pcnt;
@@ -1668,12 +1668,14 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
double percent = 0.0;
h = annotation__histogram(notes, evidx + k);
+ nr_samples = h->addr[i];
if (h->sum)
- percent = 100.0 * h->addr[i] / h->sum;
+ percent = 100.0 * nr_samples / h->sum;
if (percent > percent_max)
percent_max = percent;
src_line->samples[k].percent = percent;
+ src_line->samples[k].nr = nr_samples;
}
if (percent_max <= 0.5)
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 09776b5..948aa8e 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -98,7 +98,7 @@ struct cyc_hist {
struct source_line_samples {
double percent;
double percent_sum;
- double nr;
+ u64 nr;
};
struct source_line {
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 4/7] perf annotate: More exactly grep -v in symbol__disassemble()
2017-03-09 17:35 [PATCH v3 0/7] perf annotate: Fixes & Introduce --source-only and new source code view Taeung Song
` (2 preceding siblings ...)
2017-03-09 17:35 ` [PATCH v3 3/7] perf annotate: Fix missing setting nr samples on source_line Taeung Song
@ 2017-03-09 17:35 ` Taeung Song
2017-03-09 17:35 ` [PATCH v3 5/7] perf annotate: Get correct line numbers matched with addr Taeung Song
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Taeung Song @ 2017-03-09 17:35 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar,
Peter Zijlstra, Wang Nan, Masami Hiramatsu, Taeung Song,
Jiri Olsa
To remove the first line containing file name and file format as below,
$ objdump -l -d -S -C /home/taeung/a.out | head -2
/home/taeung/a.out: file format elf64-x86-64
currently perf-annotate use objdump with grep -v "file name".
But it cause a side effect eliminating filename:linenr of
output of 'objdump -l' so fix it.
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/util/annotate.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 63130ec..e49eb7e 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1443,7 +1443,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
snprintf(command, sizeof(command),
"%s %s%s --start-address=0x%016" PRIx64
" --stop-address=0x%016" PRIx64
- " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand",
+ " -l -d %s %s -C %s 2>/dev/null|grep -v %s: |expand",
objdump_path ? objdump_path : "objdump",
disassembler_style ? "-M " : "",
disassembler_style ? disassembler_style : "",
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 5/7] perf annotate: Get correct line numbers matched with addr
2017-03-09 17:35 [PATCH v3 0/7] perf annotate: Fixes & Introduce --source-only and new source code view Taeung Song
` (3 preceding siblings ...)
2017-03-09 17:35 ` [PATCH v3 4/7] perf annotate: More exactly grep -v in symbol__disassemble() Taeung Song
@ 2017-03-09 17:35 ` Taeung Song
2017-03-09 17:35 ` [PATCH v3 6/7] perf annotate: Introduce --source-only option Taeung Song
2017-03-09 17:35 ` [PATCH v3 7/7] perf annotate: Support the new source code view for TUI Taeung Song
6 siblings, 0 replies; 8+ messages in thread
From: Taeung Song @ 2017-03-09 17:35 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar,
Peter Zijlstra, Wang Nan, Masami Hiramatsu, Taeung Song,
Jiri Olsa
Currently perf-annotate show wrong line numbers.
For example,
Actual source code is as below
...
21 };
22
23 unsigned int limited_wgt;
24
25 unsigned int get_cond_maxprice(int wgt)
26 {
...
However, the output of perf-annotate is as below.
4 Disassembly of section .text:
6 0000000000400966 <get_cond_maxprice>:
7 get_cond_maxprice():
26 };
28 unsigned int limited_wgt;
30 unsigned int get_cond_maxprice(int wgt)
31 {
So remove the wrong way counting line numbers
and match correct line numbers to each addr of asm lines
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/util/annotate.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index e49eb7e..a50d949 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -823,11 +823,11 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line,
if (dl != NULL) {
dl->offset = offset;
dl->line = strdup(line);
- dl->line_nr = line_nr;
if (dl->line == NULL)
goto out_delete;
if (offset != -1) {
+ dl->line_nr = line_nr;
if (disasm_line__parse(dl->line, &dl->ins.name, &dl->ops.raw) < 0)
goto out_free_line;
@@ -1207,7 +1207,6 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
dl = disasm_line__new(offset, parsed_line, privsize, *line_nr, arch, map);
free(line);
- (*line_nr)++;
if (dl == NULL)
return -1;
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 6/7] perf annotate: Introduce --source-only option
2017-03-09 17:35 [PATCH v3 0/7] perf annotate: Fixes & Introduce --source-only and new source code view Taeung Song
` (4 preceding siblings ...)
2017-03-09 17:35 ` [PATCH v3 5/7] perf annotate: Get correct line numbers matched with addr Taeung Song
@ 2017-03-09 17:35 ` Taeung Song
2017-03-09 17:35 ` [PATCH v3 7/7] perf annotate: Support the new source code view for TUI Taeung Song
6 siblings, 0 replies; 8+ messages in thread
From: Taeung Song @ 2017-03-09 17:35 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar,
Peter Zijlstra, Wang Nan, Masami Hiramatsu, Taeung Song,
Jiri Olsa
Currently there is an asm view that can show
parts of source code lines with --source option.
But I think it is nice to add the new view with
--source-only into perf-annotate.
The option can show acutal source code per symbol(function)
with overhead using new struct source_code.
I think this view can be more readable than previous source
code view and be the new view point for performance
for a precheck before assembly code level.
For example, if target symbol is 'hex2u64' of util/util.c
Before:
$ perf annotate --stdio -s hex2u64
Percent | Source code & Disassembly of perf for cycles:ppp (42 samples)
-----------------------------------------------------------------------------
...
: int hex2u64(const char *ptr, u64 *long_val)
: {
0.00 : 53feb3: push %rbp
2.38 : 53feb4: mov %rsp,%rbp
0.00 : 53feb7: sub $0x30,%rsp
0.00 : 53febb: callq 4248b0 <pthread_attr_setdetachstate@plt+0x10>
0.00 : 53fec0: mov %rdi,-0x28(%rbp)
0.00 : 53fec4: mov %rsi,-0x30(%rbp)
0.00 : 53fec8: mov %fs:0x28,%rax
0.00 : 53fed1: mov %rax,-0x8(%rbp)
0.00 : 53fed5: xor %eax,%eax
: const char *p = ptr;
2.38 : 53fed7: mov -0x28(%rbp),%rax
0.00 : 53fedb: mov %rax,-0x10(%rbp)
...
After:
$ perf annotate --source-only --stdio -s hex2u64
Percent | Source code of util.c for cycles:ppp (42 samples)
-----------------------------------------------------------------
0.00 : 354 * While we find nice hex chars, build a long_val.
0.00 : 355 * Return number of chars processed.
0.00 : 356 */
0.00 : 357 int hex2u64(const char *ptr, u64 *long_val)
2.38 : 358 {
2.38 : 359 const char *p = ptr;
0.00 : 360 *long_val = 0;
0.00 : 361
30.95 : 362 while (*p) {
23.81 : 363 const int hex_val = hex(*p);
0.00 : 364
14.29 : 365 if (hex_val < 0)
0.00 : 366 break;
0.00 : 367
26.19 : 368 *long_val = (*long_val << 4) | hex_val;
0.00 : 369 p++;
0.00 : 370 }
0.00 : 371
0.00 : 372 return p - ptr;
0.00 : 373 }
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/builtin-annotate.c | 2 +
tools/perf/ui/browsers/annotate.c | 5 -
tools/perf/util/annotate.c | 299 +++++++++++++++++++++++++++++++++++++-
tools/perf/util/annotate.h | 22 +++
tools/perf/util/symbol.c | 1 +
tools/perf/util/symbol.h | 1 +
6 files changed, 321 insertions(+), 9 deletions(-)
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 4f52d85..93365e1 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -432,6 +432,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
symbol__config_symfs),
OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
"Interleave source code with assembly code (default)"),
+ OPT_BOOLEAN(0, "source-only", &symbol_conf.annotate_src_only,
+ "Display source code for each symbol"),
OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
"Display raw encoding of assembly instructions (default)"),
OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index ba36aac..03b2012 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -11,11 +11,6 @@
#include "../../util/config.h"
#include <pthread.h>
-struct disasm_line_samples {
- double percent;
- u64 nr;
-};
-
#define IPC_WIDTH 6
#define CYCLES_WIDTH 6
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index a50d949..7d1c7cc 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1357,6 +1357,273 @@ static const char *annotate__norm_arch(const char *arch_name)
return normalize_arch((char *)arch_name);
}
+static int parse_srcline(char *srcline, char **path, int *line_nr)
+{
+ char *sep;
+
+ if (srcline == NULL || !strcmp(srcline, SRCLINE_UNKNOWN))
+ return -1;
+
+ sep = strchr(srcline, ':');
+ if (sep) {
+ *sep = '\0';
+ *path = srcline;
+ *line_nr = strtoul(++sep, NULL, 0);
+ } else
+ return -1;
+
+ return 0;
+}
+
+static void code_line__free(struct code_line *cl)
+{
+ zfree(&cl->line);
+ zfree(&cl->matched_dl_arr);
+ zfree(&cl->samples_sum);
+ free(cl);
+}
+
+static void code_lines__free(struct list_head *code_lines)
+{
+ struct code_line *pos, *tmp;
+
+ if (list_empty(code_lines))
+ return;
+
+ list_for_each_entry_safe(pos, tmp, code_lines, node) {
+ list_del_init(&pos->node);
+ code_line__free(pos);
+ }
+}
+
+static int symbol__free_source_code(struct symbol *sym)
+{
+ struct annotation *notes = symbol__annotation(sym);
+ struct source_code *code = notes->src->code;
+
+ if (code == NULL)
+ return -1;
+
+ code_lines__free(&code->lines);
+ zfree(&code->path);
+ zfree(¬es->src->code);
+ return 0;
+}
+
+static void code_line__sum_samples(struct code_line *cl, struct disasm_line *dl,
+ struct annotation *notes, struct perf_evsel *evsel)
+{
+ int i;
+ u64 nr_samples;
+ struct sym_hist *h;
+ struct source_code *code = notes->src->code;
+
+ for (i = 0; i < code->nr_events; i++) {
+ double percent = 0.0;
+
+ h = annotation__histogram(notes, evsel->idx + i);
+ nr_samples = h->addr[dl->offset];
+ if (h->sum)
+ percent = 100.0 * nr_samples / h->sum;
+
+ cl->samples_sum[i].percent += percent;
+ cl->samples_sum[i].nr += nr_samples;
+ }
+}
+
+static void source_code__print(struct code_line *cl, int nr_events,
+ struct annotation *notes, struct perf_evsel *evsel)
+{
+ int i;
+ const char *color;
+ double percent, max_percent = 0.0;
+
+ for (i = 0; i < cl->nr_matched_dl; i++) {
+ code_line__sum_samples(cl, cl->matched_dl_arr[i], notes, evsel);
+ }
+
+ for (i = 0; i < nr_events; i++) {
+ percent = cl->samples_sum[i].percent;
+ color = get_percent_color(percent);
+ if (max_percent < percent)
+ max_percent = percent;
+
+ if (symbol_conf.show_total_period)
+ color_fprintf(stdout, color, " %7" PRIu64,
+ cl->samples_sum[i].nr);
+ else
+ color_fprintf(stdout, color, " %7.2f", percent);
+ }
+ color = get_percent_color(max_percent);
+ color_fprintf(stdout, color, " : %d %s\n",
+ cl->line_nr, cl->line);
+}
+
+static int code_line__match_with_dl(struct code_line *cl, struct list_head *disasm_lines)
+{
+ int nr_dl = 0;
+ struct disasm_line *pos, **tmp, **matched_dl_arr;
+ size_t allocated = sizeof(struct disasm_line **);
+
+ matched_dl_arr = zalloc(allocated);
+ if (!matched_dl_arr)
+ return -1;
+
+ list_for_each_entry(pos, disasm_lines, node) {
+ if (pos->line_nr == cl->line_nr) {
+ if (nr_dl > 0) {
+ tmp = realloc(matched_dl_arr, allocated * (nr_dl + 1));
+ if (!tmp) {
+ free(matched_dl_arr);
+ return -1;
+ }
+ matched_dl_arr = tmp;
+ }
+ matched_dl_arr[nr_dl++] = pos;
+ }
+ }
+
+ cl->matched_dl_arr = matched_dl_arr;
+ cl->nr_matched_dl = nr_dl;
+ return 0;
+}
+
+static struct code_line *code_line__new(char *line, int linenr, int nr_events)
+{
+ struct code_line *cl = zalloc(sizeof(*cl));
+
+ if (!cl)
+ return NULL;
+
+ cl->line_nr = linenr;
+ cl->line = strdup(line);
+ cl->samples_sum =
+ zalloc(sizeof(struct disasm_line_samples) * nr_events);
+ if (!cl->samples_sum)
+ zfree(&cl);
+
+ return cl;
+}
+
+static int source_code__collect(struct source_code *code,
+ struct annotation *notes,
+ char *path, char* d_name,
+ int start_linenr, int end_linenr)
+{
+ int ret = -1, linenr = 0;
+ char *line = NULL, *parsed_line;
+ size_t len;
+ FILE *file;
+ struct stat srcfile_st, objfile_st;
+ struct code_line *cl;
+
+ if (stat(path, &srcfile_st) < 0)
+ return -1;
+ else {
+ if (stat(d_name, &objfile_st) < 0)
+ return -1;
+ if (srcfile_st.st_mtime > objfile_st.st_mtime) {
+ pr_err("Source file is more recent than when recording"
+ ": %s\n", path);
+ pr_err(" (try 'perf record' again after recompiling"
+ " the source file or with 'perf buildid-cache -r')\n");
+ return -1;
+ }
+ }
+
+ file = fopen(path, "r");
+ if (!file)
+ return -1;
+
+ if (srcline_full_filename)
+ code->path = strdup(path);
+ else
+ code->path = strdup(basename(path));
+
+ INIT_LIST_HEAD(&code->lines);
+ while (!feof(file)) {
+ if (getline(&line, &len, file) < 0)
+ goto out_err;
+
+ if (++linenr < start_linenr)
+ continue;
+
+ parsed_line = rtrim(line);
+ cl = code_line__new(parsed_line, linenr, code->nr_events);
+ if (!cl)
+ goto out_err;
+ if (code_line__match_with_dl(cl, ¬es->src->source) < 0)
+ goto out_err;
+
+ list_add_tail(&cl->node, &code->lines);
+ if (linenr == end_linenr) {
+ ret = 0;
+ goto out;
+ }
+ }
+out_err:
+ code_lines__free(&code->lines);
+out:
+ free(line);
+ fclose(file);
+ return ret;
+}
+
+static int symbol__get_source_code(struct symbol *sym, struct map *map,
+ struct perf_evsel *evsel)
+{
+ struct annotation *notes = symbol__annotation(sym);
+ struct source_code *code;
+ bool tmp;
+ u64 start = map__rip_2objdump(map, sym->start);
+ u64 end = map__rip_2objdump(map, sym->end - 1);
+ int start_linenr, end_linenr, ret = -1;
+ char *path, *start_srcline = NULL, *end_srcline = NULL;
+ char *d_name = map->dso->symsrc_filename;
+
+ if (!d_name)
+ return -1;
+
+ tmp = srcline_full_filename;
+ srcline_full_filename = true;
+ start_srcline = get_srcline(map->dso, start, NULL, false);
+ end_srcline = get_srcline(map->dso, end, NULL, false);
+ srcline_full_filename = tmp;
+
+ if (parse_srcline(start_srcline, &path, &start_linenr) < 0)
+ goto out;
+ if (parse_srcline(end_srcline, &path, &end_linenr) < 0)
+ goto out;
+
+ code = zalloc(sizeof(struct source_code));
+ if (code == NULL)
+ goto out;
+
+ if (perf_evsel__is_group_event(evsel))
+ code->nr_events = evsel->nr_members;
+ else
+ code->nr_events = 1;
+
+ /* To read a function header for the sym */
+ if (start_linenr > 4)
+ start_linenr -= 4;
+ else
+ start_linenr = 1;
+
+ if (source_code__collect(code, notes, path, d_name,
+ start_linenr, end_linenr) < 0) {
+ zfree(&code);
+ goto out;
+ }
+
+ ret = 0;
+ notes->src->code = code;
+out:
+ free_srcline(start_srcline);
+ free_srcline(end_srcline);
+ return ret;
+}
+
int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_name, size_t privsize)
{
struct dso *dso = map->dso;
@@ -1497,7 +1764,6 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
if (nline == 0)
pr_err("No output from %s\n", command);
-
/*
* kallsyms does not have symbol sizes so there may a nop at the end.
* Remove it.
@@ -1755,6 +2021,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
struct sym_hist *h = annotation__histogram(notes, evsel->idx);
struct disasm_line *pos, *queue = NULL;
u64 start = map__rip_2objdump(map, sym->start);
+ bool src_code_only = false;
int printed = 2, queue_len = 0;
int more = 0;
u64 len;
@@ -1775,8 +2042,14 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
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, "Percent", d_filename, evsel_name, h->sum);
+ if (symbol_conf.annotate_src_only && notes->src->has_src_code)
+ src_code_only = true;
+
+ graph_dotted_len = printf(" %-*.*s| %s of %s for %s (%" PRIu64 " samples)\n",
+ width, width, "Percent",
+ src_code_only ? "Source code" : "Source code & Disassembly",
+ src_code_only ? notes->src->code->path : d_filename,
+ evsel_name, h->sum);
printf("%-*.*s----\n",
graph_dotted_len, graph_dotted_len, graph_dotted_line);
@@ -1784,6 +2057,16 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
if (verbose > 0)
symbol__annotate_hits(sym, evsel);
+ if (src_code_only) {
+ struct source_code *code = notes->src->code;
+ struct code_line *cl;
+
+ list_for_each_entry(cl, &code->lines, node)
+ source_code__print(cl, code->nr_events, notes, evsel);
+
+ goto out;
+ }
+
list_for_each_entry(pos, ¬es->src->source, node) {
if (context && queue == NULL) {
queue = pos;
@@ -1820,7 +2103,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
break;
}
}
-
+out:
+ printf("\n");
free(filename);
return more;
@@ -1890,6 +2174,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
bool full_paths, int min_pcnt, int max_lines)
{
struct dso *dso = map->dso;
+ struct annotation *notes = symbol__annotation(sym);
struct rb_root source_line = RB_ROOT;
u64 len;
@@ -1904,11 +2189,17 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
print_summary(&source_line, dso->long_name);
}
+ if (symbol_conf.annotate_src_only &&
+ symbol__get_source_code(sym, map, evsel) == 0)
+ notes->src->has_src_code = true;
+
symbol__annotate_printf(sym, map, evsel, full_paths,
min_pcnt, max_lines, 0);
if (print_lines)
symbol__free_source_line(sym, len);
+ if (notes->src->has_src_code)
+ symbol__free_source_code(sym);
disasm__purge(&symbol__annotation(sym)->src->source);
return 0;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 948aa8e..dd7ddae 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -56,6 +56,11 @@ int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *
struct annotation;
+struct disasm_line_samples {
+ double percent;
+ u64 nr;
+};
+
struct disasm_line {
struct list_head node;
s64 offset;
@@ -95,6 +100,21 @@ struct cyc_hist {
u16 reset;
};
+struct code_line {
+ struct list_head node;
+ int line_nr;
+ char *line;
+ int nr_matched_dl;
+ struct disasm_line **matched_dl_arr;
+ struct disasm_line_samples *samples_sum;
+};
+
+struct source_code {
+ char *path;
+ int nr_events;
+ struct list_head lines;
+};
+
struct source_line_samples {
double percent;
double percent_sum;
@@ -123,7 +143,9 @@ struct source_line {
*/
struct annotated_source {
struct list_head source;
+ struct source_code *code;
struct source_line *lines;
+ bool has_src_code;
int nr_histograms;
size_t sizeof_sym_hist;
struct cyc_hist *cycles_hist;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 70e389b..71228bd 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -35,6 +35,7 @@ struct symbol_conf symbol_conf = {
.use_modules = true,
.try_vmlinux_path = true,
.annotate_src = true,
+ .annotate_src_only = false,
.demangle = true,
.demangle_kernel = false,
.cumulate_callchain = true,
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 6c358b7..190be1d 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -108,6 +108,7 @@ struct symbol_conf {
kptr_restrict,
annotate_asm_raw,
annotate_src,
+ annotate_src_only,
event_group,
demangle,
demangle_kernel,
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 7/7] perf annotate: Support the new source code view for TUI
2017-03-09 17:35 [PATCH v3 0/7] perf annotate: Fixes & Introduce --source-only and new source code view Taeung Song
` (5 preceding siblings ...)
2017-03-09 17:35 ` [PATCH v3 6/7] perf annotate: Introduce --source-only option Taeung Song
@ 2017-03-09 17:35 ` Taeung Song
6 siblings, 0 replies; 8+ messages in thread
From: Taeung Song @ 2017-03-09 17:35 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar,
Peter Zijlstra, Wang Nan, Masami Hiramatsu, Taeung Song,
Jiri Olsa
To make source code view more readable,
add the new source code view for TUI
instead of confusing mixed source code & dissambly view.
This view can show source code per symbol(function).
and it can be toggled by a 's' key.
And support 'k' and 't' key for line numbers and total period.
For example, if target symbol is 'hex2u64' of util/util.c
Before:
| Disassembly of section .text:
|
| 000000000053ef9e <hex2u64>:
| hex2u64():
| /*
| * While we find nice hex chars, build a long_val.
| * Return number of chars processed.
| */
| int hex2u64(const char *ptr, u64 *long_val)
| {
| push %rbp
1.79 | mov %rsp,%rbp
| sub $0x30,%rsp
After:
| * While we find nice hex chars, build a long_val.
| * Return number of chars processed.
| */
| int hex2u64(const char *ptr, u64 *long_val)
1.79 | {
| const char *p = ptr;
| *long_val = 0;
|
28.57 | while (*p) {
30.36 | const int hex_val = hex(*p);
|
12.50 | if (hex_val < 0)
| break;
|
23.21 | *long_val = (*long_val << 4) | hex_val;
| p++;
| }
|
1.79 | return p - ptr;
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/Documentation/perfconfig.example | 1 -
tools/perf/ui/browsers/annotate.c | 233 ++++++++++++++++++++--------
tools/perf/util/annotate.c | 10 +-
tools/perf/util/annotate.h | 7 +
4 files changed, 180 insertions(+), 71 deletions(-)
diff --git a/tools/perf/Documentation/perfconfig.example b/tools/perf/Documentation/perfconfig.example
index 2b477c1..c9fc41b 100644
--- a/tools/perf/Documentation/perfconfig.example
+++ b/tools/perf/Documentation/perfconfig.example
@@ -23,7 +23,6 @@
[annotate]
# Defaults
- hide_src_code = false
use_offset = true
jump_arrows = true
show_nr_jumps = false
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 03b2012..ac01d75 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -27,8 +27,7 @@ struct browser_disasm_line {
};
static struct annotate_browser_opt {
- bool hide_src_code,
- use_offset,
+ bool use_offset,
jump_arrows,
show_linenr,
show_nr_jumps,
@@ -39,7 +38,7 @@ static struct annotate_browser_opt {
};
struct annotate_browser {
- struct ui_browser b;
+ struct ui_browser b, cb;
struct rb_root entries;
struct rb_node *curr_hot;
struct disasm_line *selection;
@@ -52,6 +51,7 @@ struct annotate_browser {
int nr_jumps;
bool searching_backwards;
bool have_cycles;
+ bool has_src_code;
u8 addr_width;
u8 jumps_width;
u8 target_width;
@@ -68,12 +68,9 @@ static inline struct browser_disasm_line *disasm_line__browser(struct disasm_lin
static bool disasm_line__filter(struct ui_browser *browser __maybe_unused,
void *entry)
{
- if (annotate_browser__opts.hide_src_code) {
- struct disasm_line *dl = list_entry(entry, struct disasm_line, node);
- return dl->offset == -1;
- }
+ struct disasm_line *dl = list_entry(entry, struct disasm_line, node);
- return false;
+ return dl->offset == -1;
}
static int annotate_browser__jumps_percent_color(struct annotate_browser *browser,
@@ -104,15 +101,61 @@ static int annotate_browser__pcnt_width(struct annotate_browser *ab)
return w;
}
+static void annotate_code_browser__write(struct ui_browser *browser, void *entry, int row)
+{
+ struct annotate_browser *ab = container_of(browser, struct annotate_browser, cb);
+ struct code_line *cl = list_entry(entry, struct code_line, node);
+ bool current_entry = ui_browser__is_current_entry(browser, row);
+ int i, printed;
+ double percent, max_percent = 0.0;
+ char line[256];
+
+ for (i = 0; i < ab->nr_events; i++) {
+ if (cl->samples_sum[i].percent > max_percent)
+ max_percent = cl->samples_sum[i].percent;
+ }
+
+ for (i = 0; i < ab->nr_events; i++) {
+ if (max_percent == 0.0) {
+ ui_browser__set_percent_color(browser, 0, current_entry);
+ ui_browser__write_nstring(browser, " ", 7 * ab->nr_events);
+ break;
+ }
+
+ percent = cl->samples_sum[i].percent;
+ ui_browser__set_percent_color(browser, percent, current_entry);
+
+ if (annotate_browser__opts.show_total_period)
+ ui_browser__printf(browser, "%6" PRIu64 " ",
+ cl->samples_sum[i].nr);
+ else
+ ui_browser__printf(browser, "%6.2f ", percent);
+
+ if (max_percent < percent)
+ max_percent = percent;
+ }
+
+ SLsmg_write_char(' ');
+
+ if (annotate_browser__opts.show_linenr)
+ printed = scnprintf(line, sizeof(line), "%-*d ",
+ ab->addr_width + 2, cl->line_nr);
+ else
+ printed = scnprintf(line, sizeof(line), "%*s ",
+ ab->addr_width, " ");
+
+ ui_browser__write_nstring(browser, line, printed);
+ ui_browser__write_nstring(browser, cl->line, browser->width);
+}
+
static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
{
struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
struct disasm_line *dl = list_entry(entry, struct disasm_line, node);
struct browser_disasm_line *bdl = disasm_line__browser(dl);
bool current_entry = ui_browser__is_current_entry(browser, row);
- bool change_color = (!annotate_browser__opts.hide_src_code &&
- (!current_entry || (browser->use_navkeypressed &&
- !browser->navkeypressed)));
+ bool change_color = !current_entry || (browser->use_navkeypressed &&
+ !browser->navkeypressed);
int width = browser->width, printed;
int i, pcnt_width = annotate_browser__pcnt_width(ab);
double percent_max = 0.0;
@@ -271,19 +314,25 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
bcursor = disasm_line__browser(cursor);
btarget = disasm_line__browser(target);
- if (annotate_browser__opts.hide_src_code) {
- from = bcursor->idx_asm;
- to = btarget->idx_asm;
- } else {
- from = (u64)bcursor->idx;
- to = (u64)btarget->idx;
- }
+ from = bcursor->idx_asm;
+ to = btarget->idx_asm;
ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
__ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width,
from, to);
}
+static unsigned int annotate_code_browser__refresh(struct ui_browser *browser)
+{
+ struct annotate_browser *ab = container_of(browser, struct annotate_browser, cb);
+ int ret = ui_browser__list_head_refresh(browser);
+ int pcnt_width = annotate_browser__pcnt_width(ab);
+
+ ui_browser__set_color(browser, HE_COLORSET_NORMAL);
+ __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1);
+ return ret;
+}
+
static unsigned int annotate_browser__refresh(struct ui_browser *browser)
{
struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
@@ -364,12 +413,37 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser,
bpos = rb_entry(nd, struct browser_disasm_line, rb_node);
pos = ((struct disasm_line *)bpos) - 1;
idx = bpos->idx;
- if (annotate_browser__opts.hide_src_code)
- idx = bpos->idx_asm;
+ idx = bpos->idx_asm;
annotate_browser__set_top(browser, pos, idx);
browser->curr_hot = nd;
}
+static void annotate_code_browser__calc_percent(struct annotate_browser *browser,
+ struct perf_evsel *evsel)
+{
+ int i;
+ struct map_symbol *ms = browser->b.priv;
+ struct symbol *sym = ms->sym;
+ struct annotation *notes = symbol__annotation(sym);
+ struct code_line *cl;
+ struct list_head *code_lines = browser->cb.entries;
+
+ pthread_mutex_lock(¬es->lock);
+
+ list_for_each_entry(cl, code_lines, node) {
+ for (i = 0; i < browser->nr_events; i++) {
+ cl->samples_sum[i].percent = 0.0;
+ cl->samples_sum[i].nr = 0;
+ }
+
+ for (i = 0; i < cl->nr_matched_dl; i++) {
+ code_line__sum_samples(cl, cl->matched_dl_arr[i], notes, evsel);
+ }
+ }
+
+ pthread_mutex_unlock(¬es->lock);
+}
+
static void annotate_browser__calc_percent(struct annotate_browser *browser,
struct perf_evsel *evsel)
{
@@ -422,45 +496,6 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
browser->curr_hot = rb_last(&browser->entries);
}
-static bool annotate_browser__toggle_source(struct annotate_browser *browser)
-{
- struct disasm_line *dl;
- struct browser_disasm_line *bdl;
- off_t offset = browser->b.index - browser->b.top_idx;
-
- browser->b.seek(&browser->b, offset, SEEK_CUR);
- dl = list_entry(browser->b.top, struct disasm_line, node);
- bdl = disasm_line__browser(dl);
-
- if (annotate_browser__opts.hide_src_code) {
- if (bdl->idx_asm < offset)
- offset = bdl->idx;
-
- browser->b.nr_entries = browser->nr_entries;
- annotate_browser__opts.hide_src_code = false;
- browser->b.seek(&browser->b, -offset, SEEK_CUR);
- browser->b.top_idx = bdl->idx - offset;
- browser->b.index = bdl->idx;
- } else {
- if (bdl->idx_asm < 0) {
- ui_helpline__puts("Only available for assembly lines.");
- browser->b.seek(&browser->b, -offset, SEEK_CUR);
- return false;
- }
-
- if (bdl->idx_asm < offset)
- offset = bdl->idx_asm;
-
- browser->b.nr_entries = browser->nr_asm_entries;
- annotate_browser__opts.hide_src_code = true;
- browser->b.seek(&browser->b, -offset, SEEK_CUR);
- browser->b.top_idx = bdl->idx_asm - offset;
- browser->b.index = bdl->idx_asm;
- }
-
- return true;
-}
-
static void annotate_browser__init_asm_mode(struct annotate_browser *browser)
{
ui_browser__reset_index(&browser->b);
@@ -696,6 +731,54 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser
browser->addr_width += browser->jumps_width + 1;
}
+static int annotate_code_browser__run(struct annotate_browser *browser,
+ struct perf_evsel *evsel, int delay_secs)
+{
+ int key;
+
+ if (ui_browser__show(&browser->cb, browser->cb.title, ui_helpline__current) < 0)
+ return -1;
+ annotate_code_browser__calc_percent(browser, evsel);
+
+ while (1) {
+
+ key = ui_browser__run(&browser->cb, delay_secs);
+ if (delay_secs != 0) {
+ annotate_code_browser__calc_percent(browser, evsel);
+ }
+
+ switch (key) {
+ case K_F1:
+ case 'h':
+ ui_browser__help_window(&browser->cb,
+ "UP/DOWN/PGUP\n"
+ "PGDN/SPACE Navigate\n"
+ "q/ESC/CTRL+C Return to dissembly view\n\n"
+ "s Toggle source code view\n"
+ "t Toggle total period view\n"
+ "k Toggle line numbers\n");
+ continue;
+ case 't':
+ annotate_browser__opts.show_total_period =
+ !annotate_browser__opts.show_total_period;
+ continue;
+ case 'k':
+ annotate_browser__opts.show_linenr =
+ !annotate_browser__opts.show_linenr;
+ continue;
+ case 's':
+ case K_LEFT:
+ case K_ESC:
+ case 'q':
+ case CTRL('c'):
+ return 0;
+ default:
+ continue;
+ }
+ }
+ return 0;
+}
+
static int annotate_browser__run(struct annotate_browser *browser,
struct perf_evsel *evsel,
struct hist_browser_timer *hbt)
@@ -775,7 +858,6 @@ static int annotate_browser__run(struct annotate_browser *browser,
"s Toggle source code view\n"
"t Toggle total period view\n"
"/ Search string\n"
- "k Toggle line numbers\n"
"r Run available scripts\n"
"? Search string backwards\n");
continue;
@@ -792,8 +874,11 @@ static int annotate_browser__run(struct annotate_browser *browser,
nd = browser->curr_hot;
break;
case 's':
- if (annotate_browser__toggle_source(browser))
- ui_helpline__puts(help);
+ if (browser->has_src_code) {
+ browser->cb.title = title;
+ annotate_code_browser__run(browser, evsel, delay_secs);
+ } else
+ ui_helpline__puts("No source code for the symbol");
continue;
case 'o':
annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset;
@@ -1095,9 +1180,27 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
browser.b.entries = ¬es->src->source,
browser.b.width += 18; /* Percentage */
- if (annotate_browser__opts.hide_src_code)
- annotate_browser__init_asm_mode(&browser);
+ if (symbol__get_source_code(sym, map, evsel) == 0) {
+ struct source_code *code = notes->src->code;
+ struct code_line *cl;
+
+ browser.has_src_code = true;
+ browser.cb.refresh = annotate_code_browser__refresh;
+ browser.cb.seek = ui_browser__list_head_seek;
+ browser.cb.write = annotate_code_browser__write;
+ browser.cb.use_navkeypressed = true;
+ browser.cb.entries = &code->lines;
+
+ list_for_each_entry(cl, &code->lines, node) {
+ size_t line_len = strlen(cl->line);
+
+ if (browser.cb.width < line_len)
+ browser.cb.width = line_len;
+ browser.cb.nr_entries++;
+ }
+ }
+ annotate_browser__init_asm_mode(&browser);
annotate_browser__update_addr_width(&browser);
ret = annotate_browser__run(&browser, evsel, hbt);
@@ -1105,6 +1208,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
list_del(&pos->node);
disasm_line__free(pos);
}
+ symbol__free_source_code(sym);
out_free_offsets:
free(browser.offsets);
@@ -1121,7 +1225,6 @@ static struct annotate_config {
const char *name;
bool *value;
} annotate__configs[] = {
- ANNOTATE_CFG(hide_src_code),
ANNOTATE_CFG(jump_arrows),
ANNOTATE_CFG(show_linenr),
ANNOTATE_CFG(show_nr_jumps),
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7d1c7cc..d8a3a50 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1396,7 +1396,7 @@ static void code_lines__free(struct list_head *code_lines)
}
}
-static int symbol__free_source_code(struct symbol *sym)
+int symbol__free_source_code(struct symbol *sym)
{
struct annotation *notes = symbol__annotation(sym);
struct source_code *code = notes->src->code;
@@ -1410,8 +1410,8 @@ static int symbol__free_source_code(struct symbol *sym)
return 0;
}
-static void code_line__sum_samples(struct code_line *cl, struct disasm_line *dl,
- struct annotation *notes, struct perf_evsel *evsel)
+void code_line__sum_samples(struct code_line *cl, struct disasm_line *dl,
+ struct annotation *notes, struct perf_evsel *evsel)
{
int i;
u64 nr_samples;
@@ -1569,8 +1569,8 @@ static int source_code__collect(struct source_code *code,
return ret;
}
-static int symbol__get_source_code(struct symbol *sym, struct map *map,
- struct perf_evsel *evsel)
+int symbol__get_source_code(struct symbol *sym, struct map *map,
+ struct perf_evsel *evsel)
{
struct annotation *notes = symbol__annotation(sym);
struct source_code *code;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index dd7ddae..e125eca 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -109,6 +109,9 @@ struct code_line {
struct disasm_line_samples *samples_sum;
};
+void code_line__sum_samples(struct code_line *cl, struct disasm_line *dl,
+ struct annotation *notes, struct perf_evsel *evsel);
+
struct source_code {
char *path;
int nr_events;
@@ -180,6 +183,10 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
int symbol__alloc_hist(struct symbol *sym);
void symbol__annotate_zero_histograms(struct symbol *sym);
+int symbol__free_source_code(struct symbol *sym);
+int symbol__get_source_code(struct symbol *sym, struct map *map,
+ struct perf_evsel *evsel);
+
int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_name, size_t privsize);
enum symbol_disassemble_errno {
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread