2012-11-09 17:28:35

by Namhyung Kim

[permalink] [raw]
Subject: [PATCHSET 00/13] perf annotate: Add support for event group view (v1)

Hi,

This is a patchset to support event grouping on perf annotate.

It depends on perf report event group view patchset [1] and contains
a couple of annotate fixup/cleanup patches that I sent yesterday
(although I fixed a compile problem and added a cleanup patch).

The symbol histograms already contain hit counts for every event so it
was relatively easier to support than that of perf report case. I added
a sort of flexible array to struct source_line and browser_disasm_line
for gathering percent values for each group members.

Patch 0001-0004 are cleanups and can be merged separately. I sent
similar patches yesterday, and this is the up-to-date version.
Patch 0005-0006 are preparation for later patches and
Patch 0007 added event group view for --stdio.
Patch 0008-0009 added event group view for --print-line and
Patch 0010-0012 added event group view for --tui.
Patch 0013 added --group option to enable group view suport.

Let me show you an example:

$ perf annotate --group --stdio --print-line

Sorted summary for file /lib/ld-2.11.1.so
----------------------------------------------

33.33 0.00 /build/buildd/eglibc-2.11.1/elf/rtld.c:381
33.33 0.00 /build/buildd/eglibc-2.11.1/elf/dynamic-link.h:128
33.33 0.00 /build/buildd/eglibc-2.11.1/elf/do-rel.h:105
0.00 75.00 /build/buildd/eglibc-2.11.1/elf/dynamic-link.h:137
0.00 25.00 /build/buildd/eglibc-2.11.1/elf/dynamic-link.h:187
Percent | Source code & Disassembly of ld-2.11.1.so
------------------------------------------------------------------
:
:
:
: Disassembly of section .text:
:
: 0000000000001120 <_dl_rtld_di_serinfo-0x7a20>:
0.00 0.00 : 1120: push %rbp
0.00 0.00 : 1121: mov %rsp,%rbp
0.00 0.00 : 1124: push %r15
0.00 0.00 : 1126: push %r14
0.00 0.00 : 1128: push %r13
0.00 0.00 : 112a: push %r12
0.00 0.00 : 112c: push %rbx
0.00 0.00 : 112d: mov %rdi,%rbx
0.00 0.00 : 1130: sub $0x28,%rsp
0.00 0.00 : 1134: rdtsc
0.00 0.00 : 1136: shl $0x20,%rdx
0.00 0.00 : 113a: mov %eax,%eax
0.00 0.00 : 113c: or %rax,%rdx
0.00 0.00 : 113f: lea -0x26(%rip),%r13 # 1120 <free@plt+0x648>
0.00 0.00 : 1146: sub 0x21ea93(%rip),%r13 # 21fbe0 <calloc+0x208c80>
/build/buildd/eglibc-2.11.1/elf/rtld.c:381
33.33 0.00 : 114d: mov %rdx,0x21ec54(%rip) # 21fda8 <_rtld_global_ro+0x1a8>
0.00 0.00 : 1154: mov %r13,%rdx
...


You can access it via my tree as well.

git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git perf/annotate-group-v1

As always, any comments are welcome, thanks.
Namhyung


[1] http://www.mail-archive.com/[email protected]/msg337706.html

Namhyung Kim (13):
perf annotate: Parse --asm-raw output properly
perf annotate: Whitespace fixups
perf annotate: Merge same lines in summary view
perf annotate: Don't try to follow jump target on PLT symbols
perf annotate: Pass evsel instead of evidx on annotation functions
perf annotate: Factor out disasm__calc_percent()
perf annotate: Basic support for event group view
perf annotate: Factor out struct source_line_percent
perf annotate: Support event group view for --print-line
perf annotate browser: Make browser_disasm_line->percent an array
perf annotate browser: Use disasm__calc_percent()
perf annotate browser: Support event group view on TUI
perf annotate: Add --group option

tools/perf/builtin-annotate.c | 20 ++-
tools/perf/builtin-top.c | 2 +-
tools/perf/ui/browsers/annotate.c | 151 ++++++++++------
tools/perf/ui/browsers/hists.c | 2 +-
tools/perf/util/annotate.c | 349 ++++++++++++++++++++++++++++++-------
tools/perf/util/annotate.h | 28 ++-
tools/perf/util/hist.h | 5 +-
7 files changed, 418 insertions(+), 139 deletions(-)

--
1.7.9.2


2012-11-09 17:28:42

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 01/13] perf annotate: Parse --asm-raw output properly

From: Namhyung Kim <[email protected]>

If --asm-raw option was given, objdump output will contain hex numbers
of the instruction before the symbolic name. However current parser
code doesn't handle it properly. Fix it.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/ui/browsers/annotate.c | 2 ++
tools/perf/util/annotate.c | 36 ++++++++++++++++++++++++++++++++++--
2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 3eff17f703f3..aec11f34d394 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -117,6 +117,8 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
ab->addr_width, " ");
slsmg_write_nstring(bf, printed);
slsmg_write_nstring(dl->line, width - printed - 6);
+ } else if (!dl->name) {
+ slsmg_write_nstring(" ", width - 7);
} else {
u64 addr = dl->offset;
int color = -1;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index b14d4df9f149..0565558b6184 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -162,7 +162,7 @@ static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)

static int lock__parse(struct ins_operands *ops)
{
- char *name;
+ char *name = NULL;

ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
if (ops->locked.ops == NULL)
@@ -171,7 +171,10 @@ static int lock__parse(struct ins_operands *ops)
if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
goto out_free_ops;

- ops->locked.ins = ins__find(name);
+ if (name == NULL)
+ goto out_free_ops;
+
+ ops->locked.ins = ins__find(name);
if (ops->locked.ins == NULL)
goto out_free_ops;

@@ -492,6 +495,9 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,

static void disasm_line__init_ins(struct disasm_line *dl)
{
+ if (dl->name == NULL)
+ return;
+
dl->ins = ins__find(dl->name);

if (dl->ins == NULL)
@@ -514,6 +520,32 @@ static int disasm_line__parse(char *line, char **namep, char **rawp)
if (name[0] == '\0')
return -1;

+ if (symbol_conf.annotate_asm_raw) {
+ /*
+ * If --asm-raw option was given, objdump output will contain
+ * hex numbers of the instructions before the symbolic name.
+ * They are separated by at least two space characters:
+ *
+ * 400540: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp)
+ * 400547: 00
+ *
+ * It sometimes was broken to multiple lines due to a limited
+ * width. In this case following condition will be met:
+ *
+ * dl->offset != -1 && dl->name == NULL.
+ */
+ name = strstr(name, " ");
+ if (name == NULL)
+ return 0;
+
+ while (isspace(name[0]))
+ ++name;
+
+ if (name[0] == '\0')
+ return -1;
+
+ }
+
*rawp = name + 1;

while ((*rawp)[0] != '\0' && !isspace((*rawp)[0]))
--
1.7.9.2

2012-11-09 17:28:49

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 02/13] perf annotate: Whitespace fixups

Some lines are indented by whitespace characters rather than tabs.
Fix them.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/util/annotate.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 0565558b6184..12287b121669 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -175,14 +175,14 @@ static int lock__parse(struct ins_operands *ops)
goto out_free_ops;

ops->locked.ins = ins__find(name);
- if (ops->locked.ins == NULL)
- goto out_free_ops;
+ if (ops->locked.ins == NULL)
+ goto out_free_ops;

- if (!ops->locked.ins->ops)
- return 0;
+ if (!ops->locked.ins->ops)
+ return 0;

- if (ops->locked.ins->ops->parse)
- ops->locked.ins->ops->parse(ops->locked.ops);
+ if (ops->locked.ins->ops->parse)
+ ops->locked.ins->ops->parse(ops->locked.ops);

return 0;

--
1.7.9.2

2012-11-09 17:28:55

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 04/13] perf annotate: Don't try to follow jump target on PLT symbols

From: Namhyung Kim <[email protected]>

The perf annotate browser on TUI can identify a jump target for a
selected instruction. It assumes that the jump target is within the
function but it's not the case of PLT symbols which have offset out of
the function as a target. Since it caused a segmentation fault, do
not try to follow jump target on the PLT symbols.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/ui/browsers/annotate.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index aec11f34d394..bb393dd26ba2 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -190,6 +190,12 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
struct disasm_line *cursor = ab->selection, *target;
struct browser_disasm_line *btarget, *bcursor;
unsigned int from, to;
+ struct map_symbol *ms = ab->b.priv;
+ struct symbol *sym = ms->sym;
+
+ /* PLT symbols contain external offsets */
+ if (strstr(sym->name, "@plt"))
+ return;

if (!cursor || !cursor->ins || !ins__is_jump(cursor->ins) ||
!disasm_line__has_offset(cursor))
@@ -773,6 +779,12 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browser
size_t size)
{
u64 offset;
+ struct map_symbol *ms = browser->b.priv;
+ struct symbol *sym = ms->sym;
+
+ /* PLT symbols contain external offsets */
+ if (strstr(sym->name, "@plt"))
+ return;

for (offset = 0; offset < size; ++offset) {
struct disasm_line *dl = browser->offsets[offset], *dlt;
--
1.7.9.2

2012-11-09 17:29:04

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 06/13] perf annotate: Factor out disasm__calc_percent()

From: Namhyung Kim <[email protected]>

Factor out calculation of histogram of a symbol into
disasm__calc_percent. It'll be used for event group view.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/util/annotate.c | 52 +++++++++++++++++++++++++++++---------------
1 file changed, 35 insertions(+), 17 deletions(-)

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 3a088a367c52..f985866304ff 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -635,6 +635,38 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa
return NULL;
}

+static void disasm__calc_percent(struct symbol *sym, struct perf_evsel *evsel,
+ s64 from, s64 to, const char **path,
+ double *percent)
+{
+ struct annotation *notes = symbol__annotation(sym);
+ struct source_line *src_line = notes->src->lines;
+ struct sym_hist *h;
+ unsigned int hits = 0;
+ s64 offset = from;
+
+ *percent = 0.0;
+
+ if (src_line) {
+ while (offset < to) {
+ if (*path == NULL)
+ *path = src_line[offset].path;
+
+ *percent += src_line[offset].percent;
+ ++offset;
+ }
+ } else {
+ h = annotation__histogram(notes, evsel->idx);
+
+ while (offset < to) {
+ hits += h->addr[offset];
+ }
+
+ if (h->sum)
+ *percent = 100.0 * hits / h->sum;
+ }
+}
+
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)
@@ -644,32 +676,18 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st

if (dl->offset != -1) {
const char *path = NULL;
- unsigned int hits = 0;
double percent = 0.0;
const char *color;
struct annotation *notes = symbol__annotation(sym);
- struct source_line *src_line = notes->src->lines;
- struct sym_hist *h = annotation__histogram(notes, evsel->idx);
s64 offset = dl->offset;
const u64 addr = start + offset;
struct disasm_line *next;

next = disasm__get_next_ip_line(&notes->src->source, dl);

- while (offset < (s64)len &&
- (next == NULL || offset < next->offset)) {
- if (src_line) {
- if (path == NULL)
- path = src_line[offset].path;
- percent += src_line[offset].percent;
- } else
- hits += h->addr[offset];
-
- ++offset;
- }
-
- if (src_line == NULL && h->sum)
- percent = 100.0 * hits / h->sum;
+ disasm__calc_percent(sym, evsel, offset,
+ next ? next->offset : (s64) len,
+ &path, &percent);

if (percent < min_pcnt)
return -1;
--
1.7.9.2

2012-11-09 17:29:09

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 08/13] perf annotate: Factor out struct source_line_percent

From: Namhyung Kim <[email protected]>

The source_line_percent struct contains percentage value of the symbol
histogram. This is a preparation of event group view change.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/ui/browsers/annotate.c | 2 +-
tools/perf/util/annotate.c | 14 +++++++-------
tools/perf/util/annotate.h | 8 ++++++--
3 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index ad943164ece9..feea37ad37e9 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -250,7 +250,7 @@ static double disasm_line__calc_percent(struct disasm_line *dl, struct symbol *s
while (offset < (s64)len &&
(next == NULL || offset < next->offset)) {
if (src_line) {
- percent += src_line[offset].percent;
+ percent += src_line[offset].p[0].percent;
} else
hits += h->addr[offset];

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 5b44c3b1a166..42f8a9d8a9cf 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -654,7 +654,7 @@ static void disasm__calc_percent(struct symbol *sym, struct perf_evsel *evsel,
if (*path == NULL)
*path = src_line[offset].path;

- *percent += src_line[offset].percent;
+ *percent += src_line[offset].p[0].percent;
++offset;
}
} else {
@@ -959,7 +959,7 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin

ret = strcmp(iter->path, src_line->path);
if (ret == 0) {
- iter->percent_sum += src_line->percent;
+ iter->p[0].percent_sum += src_line->p[0].percent;
return;
}

@@ -969,7 +969,7 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
p = &(*p)->rb_right;
}

- src_line->percent_sum = src_line->percent;
+ src_line->p[0].percent_sum = src_line->p[0].percent;

rb_link_node(&src_line->node, parent, p);
rb_insert_color(&src_line->node, root);
@@ -985,7 +985,7 @@ static void __resort_source_line(struct rb_root *root, struct source_line *src_l
parent = *p;
iter = rb_entry(parent, struct source_line, node);

- if (src_line->percent_sum > iter->percent_sum)
+ if (src_line->p[0].percent_sum > iter->p[0].percent_sum)
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
@@ -1055,8 +1055,8 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
u64 offset;
FILE *fp;

- src_line[i].percent = 100.0 * h->addr[i] / h->sum;
- if (src_line[i].percent <= 0.5)
+ src_line[i].p[0].percent = 100.0 * h->addr[i] / h->sum;
+ if (src_line[i].p[0].percent <= 0.5)
continue;

offset = start + i;
@@ -1103,7 +1103,7 @@ static void print_summary(struct rb_root *root, const char *filename)
char *path;

src_line = rb_entry(node, struct source_line, node);
- percent = src_line->percent_sum;
+ percent = src_line->p[0].percent_sum;
color = get_percent_color(percent);
path = src_line->path;

diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 5ce9ff3ffcd7..ca2badc07653 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -73,11 +73,15 @@ struct sym_hist {
u64 addr[0];
};

-struct source_line {
- struct rb_node node;
+struct source_line_percent {
double percent;
double percent_sum;
+};
+
+struct source_line {
+ struct rb_node node;
char *path;
+ struct source_line_percent p[1];
};

/** struct annotated_source - symbols with hits have this attached as in sannotation
--
1.7.9.2

2012-11-09 17:29:15

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 10/13] perf annotate browser: Make browser_disasm_line->percent an array

Make percent field of struct browser_disasm_line an array and
move it to the last. This is a preparation of event group view
feature.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/ui/browsers/annotate.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index feea37ad37e9..a846fe36a26e 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -14,10 +14,10 @@

struct browser_disasm_line {
struct rb_node rb_node;
- double percent;
u32 idx;
int idx_asm;
int jump_sources;
+ double percent[1];
};

static struct annotate_browser_opt {
@@ -97,9 +97,9 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
int width = browser->width, printed;
char bf[256];

- if (dl->offset != -1 && bdl->percent != 0.0) {
- ui_browser__set_percent_color(browser, bdl->percent, current_entry);
- slsmg_printf("%6.2f ", bdl->percent);
+ if (dl->offset != -1 && bdl->percent[0] != 0.0) {
+ ui_browser__set_percent_color(browser, bdl->percent[0], current_entry);
+ slsmg_printf("%6.2f ", bdl->percent[0]);
} else {
ui_browser__set_percent_color(browser, 0, current_entry);
slsmg_write_nstring(" ", 7);
@@ -276,7 +276,7 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_l
while (*p != NULL) {
parent = *p;
l = rb_entry(parent, struct browser_disasm_line, rb_node);
- if (bdl->percent < l->percent)
+ if (bdl->percent[0] < l->percent[0])
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
@@ -338,8 +338,8 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,

list_for_each_entry(pos, &notes->src->source, node) {
struct browser_disasm_line *bpos = disasm_line__browser(pos);
- bpos->percent = disasm_line__calc_percent(pos, sym, evsel->idx);
- if (bpos->percent < 0.01) {
+ bpos->percent[0] = disasm_line__calc_percent(pos, sym, evsel->idx);
+ if (bpos->percent[0] < 0.01) {
RB_CLEAR_NODE(&bpos->rb_node);
continue;
}
--
1.7.9.2

2012-11-09 17:29:22

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 12/13] perf annotate browser: Support event group view on TUI

Dynamically allocate browser_disasm_line according to a number of
group members and save nr_pcnt to the struct. This way we can
handle multiple events in a general manner.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/ui/browsers/annotate.c | 69 ++++++++++++++++++++++++++++++-------
1 file changed, 57 insertions(+), 12 deletions(-)

diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 7df1fa990ec2..0826f8954795 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -17,6 +17,7 @@ struct browser_disasm_line {
u32 idx;
int idx_asm;
int jump_sources;
+ int nr_pcnt;
double percent[1];
};

@@ -95,14 +96,25 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
(!current_entry || (browser->use_navkeypressed &&
!browser->navkeypressed)));
int width = browser->width, printed;
+ int i, pcnt_width = 7 * bdl->nr_pcnt;
+ double percent_max = 0.0;
char bf[256];

- if (dl->offset != -1 && bdl->percent[0] != 0.0) {
- ui_browser__set_percent_color(browser, bdl->percent[0], current_entry);
- slsmg_printf("%6.2f ", bdl->percent[0]);
+ for (i = 0; i < bdl->nr_pcnt; i++) {
+ if (bdl->percent[i] > percent_max)
+ percent_max = bdl->percent[i];
+ }
+
+ if (dl->offset != -1 && percent_max != 0.0) {
+ for (i = 0; i < bdl->nr_pcnt; i++) {
+ ui_browser__set_percent_color(browser,
+ bdl->percent[i],
+ current_entry);
+ slsmg_printf("%6.2f ", bdl->percent[i]);
+ }
} else {
ui_browser__set_percent_color(browser, 0, current_entry);
- slsmg_write_nstring(" ", 7);
+ slsmg_write_nstring(" ", pcnt_width);
}

SLsmg_write_char(' ');
@@ -112,14 +124,14 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
width += 1;

if (!*dl->line)
- slsmg_write_nstring(" ", width - 7);
+ slsmg_write_nstring(" ", width - pcnt_width);
else if (dl->offset == -1) {
printed = scnprintf(bf, sizeof(bf), "%*s ",
ab->addr_width, " ");
slsmg_write_nstring(bf, printed);
- slsmg_write_nstring(dl->line, width - printed - 6);
+ slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1);
} else if (!dl->name) {
- slsmg_write_nstring(" ", width - 7);
+ slsmg_write_nstring(" ", width - pcnt_width);
} else {
u64 addr = dl->offset;
int color = -1;
@@ -178,7 +190,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
}

disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset);
- slsmg_write_nstring(bf, width - 10 - printed);
+ slsmg_write_nstring(bf, width - pcnt_width - 3 - printed);
}

if (current_entry)
@@ -193,6 +205,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
unsigned int from, to;
struct map_symbol *ms = ab->b.priv;
struct symbol *sym = ms->sym;
+ u8 pcnt_width = 7;

/* PLT symbols contain external offsets */
if (strstr(sym->name, "@plt"))
@@ -217,22 +230,43 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
to = (u64)btarget->idx;
}

+ pcnt_width *= bcursor->nr_pcnt;
+
ui_browser__set_color(browser, HE_COLORSET_CODE);
- __ui_browser__line_arrow(browser, 9 + ab->addr_width, from, to);
+ __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width,
+ from, to);
}

static unsigned int annotate_browser__refresh(struct ui_browser *browser)
{
+ struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
+ struct disasm_line *cursor = ab->offsets[0];
+ struct browser_disasm_line *bcursor = disasm_line__browser(cursor);
int ret = ui_browser__list_head_refresh(browser);
+ int pcnt_width = 7 * bcursor->nr_pcnt;

if (annotate_browser__opts.jump_arrows)
annotate_browser__draw_current_jump(browser);

ui_browser__set_color(browser, HE_COLORSET_NORMAL);
- __ui_browser__vline(browser, 7, 0, browser->height - 1);
+ __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1);
return ret;
}

+static int disasm__cmp(struct browser_disasm_line *a,
+ struct browser_disasm_line *b)
+{
+ int i;
+
+ for (i = 0; i < a->nr_pcnt; i++) {
+ if (a->percent[i] == b->percent[i])
+ continue;
+ return a->percent[i] < b->percent[i];
+ }
+
+ return 0;
+}
+
static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl)
{
struct rb_node **p = &root->rb_node;
@@ -242,7 +276,8 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_l
while (*p != NULL) {
parent = *p;
l = rb_entry(parent, struct browser_disasm_line, rb_node);
- if (bdl->percent[0] < l->percent[0])
+
+ if (disasm__cmp(bdl, l))
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
@@ -830,6 +865,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
},
};
int ret = -1;
+ int nr_pcnt = 1;
+ size_t sizeof_bdl = sizeof(struct browser_disasm_line);

if (sym == NULL)
return -1;
@@ -845,7 +882,14 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
return -1;
}

- if (symbol__annotate(sym, map, sizeof(struct browser_disasm_line)) < 0) {
+ if (symbol_conf.event_group) {
+ if (perf_evsel__is_group_leader(evsel)) {
+ sizeof_bdl += sizeof(double) * evsel->nr_members;
+ nr_pcnt += evsel->nr_members;
+ }
+ }
+
+ if (symbol__annotate(sym, map, sizeof_bdl) < 0) {
ui__error("%s", ui_helpline__last_msg);
goto out_free_offsets;
}
@@ -862,6 +906,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
if (browser.b.width < line_len)
browser.b.width = line_len;
bpos = disasm_line__browser(pos);
+ bpos->nr_pcnt = nr_pcnt;
bpos->idx = browser.nr_entries++;
if (pos->offset != -1) {
bpos->idx_asm = browser.nr_asm_entries++;
--
1.7.9.2

2012-11-09 17:29:26

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 13/13] perf annotate: Add --group option

From: Namhyung Kim <[email protected]>

Add --group option to enable event grouping. When enabled, all the
group members information will be shown together with the leader so
skip non-leader events.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/builtin-annotate.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 0c6edd60d67e..4b12608707f0 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -214,6 +214,10 @@ static int __cmd_annotate(struct perf_annotate *ann)
struct hists *hists = &pos->hists;
u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];

+ if (symbol_conf.event_group &&
+ !perf_evsel__is_group_leader(pos))
+ continue;
+
if (nr_samples > 0) {
total_nr_samples += nr_samples;
hists__collapse_resort(hists);
@@ -293,6 +297,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
"Specify disassembler style (e.g. -M intel for intel syntax)"),
OPT_STRING(0, "objdump", &objdump_path, "path",
"objdump binary to use for disassembly and annotations"),
+ OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
+ "Show event grou information together"),
OPT_END()
};

--
1.7.9.2

2012-11-09 17:29:57

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 11/13] perf annotate browser: Use disasm__calc_percent()

The disasm_line__calc_percent() which was used by annotate
browser code almost duplicates disasm__calc_percent. Since
the latter can handle multiple events properly, use it and
get rid of the code duplication.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/ui/browsers/annotate.c | 50 +++++++++++--------------------------
tools/perf/util/annotate.c | 6 ++---
tools/perf/util/annotate.h | 3 +++
3 files changed, 20 insertions(+), 39 deletions(-)

diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index a846fe36a26e..7df1fa990ec2 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -233,40 +233,6 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser)
return ret;
}

-static double disasm_line__calc_percent(struct disasm_line *dl, struct symbol *sym, int evidx)
-{
- double percent = 0.0;
-
- if (dl->offset != -1) {
- int len = sym->end - sym->start;
- unsigned int hits = 0;
- struct annotation *notes = symbol__annotation(sym);
- struct source_line *src_line = notes->src->lines;
- struct sym_hist *h = annotation__histogram(notes, evidx);
- s64 offset = dl->offset;
- struct disasm_line *next;
-
- next = disasm__get_next_ip_line(&notes->src->source, dl);
- while (offset < (s64)len &&
- (next == NULL || offset < next->offset)) {
- if (src_line) {
- percent += src_line[offset].p[0].percent;
- } else
- hits += h->addr[offset];
-
- ++offset;
- }
- /*
- * If the percentage wasn't already calculated in
- * symbol__get_source_line, do it now:
- */
- if (src_line == NULL && h->sum)
- percent = 100.0 * hits / h->sum;
- }
-
- return percent;
-}
-
static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl)
{
struct rb_node **p = &root->rb_node;
@@ -330,7 +296,8 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
struct map_symbol *ms = browser->b.priv;
struct symbol *sym = ms->sym;
struct annotation *notes = symbol__annotation(sym);
- struct disasm_line *pos;
+ struct disasm_line *pos, *next;
+ u64 len = sym->end - sym->start;

browser->entries = RB_ROOT;

@@ -338,7 +305,18 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,

list_for_each_entry(pos, &notes->src->source, node) {
struct browser_disasm_line *bpos = disasm_line__browser(pos);
- bpos->percent[0] = disasm_line__calc_percent(pos, sym, evsel->idx);
+
+ if (pos->offset == -1) {
+ RB_CLEAR_NODE(&bpos->rb_node);
+ continue;
+ }
+
+ next = disasm__get_next_ip_line(&notes->src->source, pos);
+
+ disasm__calc_percent(sym, evsel, pos->offset,
+ next ? next->offset : (s64) len,
+ NULL, bpos->percent, 1);
+
if (bpos->percent[0] < 0.01) {
RB_CLEAR_NODE(&bpos->rb_node);
continue;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 28ac33e83bf3..41462f84feea 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -635,9 +635,9 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa
return NULL;
}

-static void disasm__calc_percent(struct symbol *sym, struct perf_evsel *evsel,
- s64 from, s64 to, const char **path,
- double *percent, int nr_percent)
+void disasm__calc_percent(struct symbol *sym, struct perf_evsel *evsel,
+ s64 from, s64 to, const char **path,
+ double *percent, int nr_percent)
{
struct annotation *notes = symbol__annotation(sym);
struct source_line *src_line = notes->src->lines;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index fa74c09f0c70..6cbb333ad518 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -67,6 +67,9 @@ void disasm_line__free(struct disasm_line *dl);
struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos);
int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
size_t disasm__fprintf(struct list_head *head, FILE *fp);
+void disasm__calc_percent(struct symbol *sym, struct perf_evsel *evsel,
+ s64 from, s64 to, const char **path,
+ double *percent, int nr_percent);

struct sym_hist {
u64 sum;
--
1.7.9.2

2012-11-09 17:30:20

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 09/13] perf annotate: Support event group view for --print-line

Dynamically allocate source_line_percent according to a number of
group members and save nr_pcnt to the struct source_line. This
way we can handle multiple events in a general manner.

However since the size of struct source_line is not fixed anymore,
iterating whole source_line should care about its size.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/util/annotate.c | 123 +++++++++++++++++++++++++++++++++-----------
tools/perf/util/annotate.h | 1 +
2 files changed, 95 insertions(+), 29 deletions(-)

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 42f8a9d8a9cf..28ac33e83bf3 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -650,11 +650,19 @@ static void disasm__calc_percent(struct symbol *sym, struct perf_evsel *evsel,
memset(percent, 0, sizeof(percent) * nr_percent);

if (src_line) {
+ size_t sizeof_src_line = sizeof(*src_line) +
+ sizeof(src_line->p) * (src_line->nr_pcnt - 1);
+
while (offset < to) {
- if (*path == NULL)
- *path = src_line[offset].path;
+ src_line = (void *)notes->src->lines +
+ (sizeof_src_line * offset);
+
+ if (path && *path == NULL)
+ *path = src_line->path;
+
+ for (i = 0; i < nr_percent; i++)
+ percent[i] += src_line->p[i].percent;

- *percent += src_line[offset].p[0].percent;
++offset;
}
} else {
@@ -951,7 +959,7 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
struct source_line *iter;
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
- int ret;
+ int i, ret;

while (*p != NULL) {
parent = *p;
@@ -959,7 +967,8 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin

ret = strcmp(iter->path, src_line->path);
if (ret == 0) {
- iter->p[0].percent_sum += src_line->p[0].percent;
+ for (i = 0; i < src_line->nr_pcnt; i++)
+ iter->p[i].percent_sum += src_line->p[i].percent;
return;
}

@@ -969,12 +978,26 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
p = &(*p)->rb_right;
}

- src_line->p[0].percent_sum = src_line->p[0].percent;
+ for (i = 0; i < src_line->nr_pcnt; i++)
+ src_line->p[i].percent_sum = src_line->p[i].percent;

rb_link_node(&src_line->node, parent, p);
rb_insert_color(&src_line->node, root);
}

+static int cmp_source_line(struct source_line *a, struct source_line *b)
+{
+ int i;
+
+ for (i = 0; i < a->nr_pcnt; i++) {
+ if (a->p[i].percent_sum == b->p[i].percent_sum)
+ continue;
+ return a->p[i].percent_sum > b->p[i].percent_sum;
+ }
+
+ return 0;
+}
+
static void __resort_source_line(struct rb_root *root, struct source_line *src_line)
{
struct source_line *iter;
@@ -985,7 +1008,7 @@ static void __resort_source_line(struct rb_root *root, struct source_line *src_l
parent = *p;
iter = rb_entry(parent, struct source_line, node);

- if (src_line->p[0].percent_sum > iter->p[0].percent_sum)
+ if (cmp_source_line(src_line, iter))
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
@@ -1017,12 +1040,18 @@ static void symbol__free_source_line(struct symbol *sym, int len)
{
struct annotation *notes = symbol__annotation(sym);
struct source_line *src_line = notes->src->lines;
+ size_t sizeof_src_line;
int i;

- for (i = 0; i < len; i++)
- free(src_line[i].path);
+ sizeof_src_line = sizeof(*src_line) +
+ (sizeof(src_line->p) * (src_line->nr_pcnt - 1));

- free(src_line);
+ for (i = 0; i < len; i++) {
+ free(src_line->path);
+ src_line = (void *)src_line + sizeof_src_line;
+ }
+
+ free(notes->src->lines);
notes->src->lines = NULL;
}

@@ -1033,17 +1062,32 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
const char *filename)
{
u64 start;
- int i;
+ int i, k;
+ int evidx = evsel->idx;
char cmd[PATH_MAX * 2];
struct source_line *src_line;
struct annotation *notes = symbol__annotation(sym);
- struct sym_hist *h = annotation__histogram(notes, evsel->idx);
+ struct sym_hist *h = annotation__histogram(notes, evidx);
struct rb_root tmp_root = RB_ROOT;
+ int nr_pcnt = 1;
+ u64 h_sum = h->sum;
+ size_t sizeof_src_line = sizeof(struct source_line);

- if (!h->sum)
+ if (symbol_conf.event_group) {
+ if (perf_evsel__is_group_leader(evsel)) {
+ for (i = 0; i < evsel->nr_members; i++) {
+ h = annotation__histogram(notes, evidx + i);
+ h_sum += h->sum;
+ }
+ nr_pcnt += evsel->nr_members;
+ sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->p);
+ }
+ }
+
+ if (!h_sum)
return 0;

- src_line = notes->src->lines = calloc(len, sizeof(struct source_line));
+ src_line = notes->src->lines = calloc(len, sizeof_src_line);
if (!notes->src->lines)
return -1;

@@ -1054,29 +1098,41 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
size_t line_len;
u64 offset;
FILE *fp;
+ double percent_max = 0.0;

- src_line[i].p[0].percent = 100.0 * h->addr[i] / h->sum;
- if (src_line[i].p[0].percent <= 0.5)
- continue;
+ src_line->nr_pcnt = nr_pcnt;
+
+ for (k = 0; k < nr_pcnt; k++) {
+ h = annotation__histogram(notes, evidx + k);
+ src_line->p[k].percent = 100.0 * h->addr[i] / h->sum;
+
+ if (src_line->p[k].percent > percent_max)
+ percent_max = src_line->p[k].percent;
+ }
+
+ if (percent_max <= 0.5)
+ goto next;

offset = start + i;
sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
fp = popen(cmd, "r");
if (!fp)
- continue;
+ goto next;

if (getline(&path, &line_len, fp) < 0 || !line_len)
- goto next;
+ goto next_close;

- src_line[i].path = malloc(sizeof(char) * line_len + 1);
- if (!src_line[i].path)
- goto next;
+ src_line->path = malloc(sizeof(char) * line_len + 1);
+ if (!src_line->path)
+ goto next_close;

- strcpy(src_line[i].path, path);
- insert_source_line(&tmp_root, &src_line[i]);
+ strcpy(src_line->path, path);
+ insert_source_line(&tmp_root, src_line);

- next:
+ next_close:
pclose(fp);
+ next:
+ src_line = (void *)src_line + sizeof_src_line;
}

resort_source_line(root, &tmp_root);
@@ -1098,16 +1154,25 @@ static void print_summary(struct rb_root *root, const char *filename)

node = rb_first(root);
while (node) {
- double percent;
+ double percent, percent_max = 0.0;
const char *color;
char *path;
+ int i;

src_line = rb_entry(node, struct source_line, node);
- percent = src_line->p[0].percent_sum;
- color = get_percent_color(percent);
+ for (i = 0; i < src_line->nr_pcnt; i++) {
+ percent = src_line->p[i].percent_sum;
+ color = get_percent_color(percent);
+ color_fprintf(stdout, color, " %7.2f", percent);
+
+ if (percent > percent_max)
+ percent_max = percent;
+ }
+
path = src_line->path;
+ color = get_percent_color(percent_max);
+ color_fprintf(stdout, color, " %s", path);

- color_fprintf(stdout, color, " %7.2f %s", percent, path);
node = rb_next(node);
}
}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index ca2badc07653..fa74c09f0c70 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -81,6 +81,7 @@ struct source_line_percent {
struct source_line {
struct rb_node node;
char *path;
+ int nr_pcnt;
struct source_line_percent p[1];
};

--
1.7.9.2

2012-11-09 17:30:47

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 07/13] perf annotate: Basic support for event group view

From: Namhyung Kim <[email protected]>

Add support for event group view when symbol_conf.event_group enabled.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/util/annotate.c | 86 +++++++++++++++++++++++++++++++++++---------
1 file changed, 69 insertions(+), 17 deletions(-)

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index f985866304ff..5b44c3b1a166 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -637,15 +637,17 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa

static void disasm__calc_percent(struct symbol *sym, struct perf_evsel *evsel,
s64 from, s64 to, const char **path,
- double *percent)
+ double *percent, int nr_percent)
{
struct annotation *notes = symbol__annotation(sym);
struct source_line *src_line = notes->src->lines;
struct sym_hist *h;
- unsigned int hits = 0;
+ unsigned int hits;
s64 offset = from;
+ int evidx = evsel->idx;
+ int i;

- *percent = 0.0;
+ memset(percent, 0, sizeof(percent) * nr_percent);

if (src_line) {
while (offset < to) {
@@ -656,14 +658,19 @@ static void disasm__calc_percent(struct symbol *sym, struct perf_evsel *evsel,
++offset;
}
} else {
- h = annotation__histogram(notes, evsel->idx);
+ for (i = 0; i < nr_percent; i++) {
+ hits = 0;
+ offset = from;
+ h = annotation__histogram(notes, evidx + i);
+
+ while (offset < to) {
+ hits += h->addr[offset];
+ offset++;
+ }

- while (offset < to) {
- hits += h->addr[offset];
+ if (h->sum)
+ percent[i] = 100.0 * hits / h->sum;
}
-
- if (h->sum)
- *percent = 100.0 * hits / h->sum;
}
}

@@ -677,19 +684,39 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
if (dl->offset != -1) {
const char *path = NULL;
double percent = 0.0;
+ double percent_max = 0.0;
+ double *ppercents = &percent;
+ int i, nr_percents = 1;
const char *color;
struct annotation *notes = symbol__annotation(sym);
s64 offset = dl->offset;
const u64 addr = start + offset;
struct disasm_line *next;

+ if (symbol_conf.event_group) {
+ if (perf_evsel__is_group_leader(evsel) &&
+ evsel->nr_members > 0) {
+ nr_percents = evsel->nr_members + 1;
+ ppercents = calloc(nr_percents, sizeof(double));
+ if (ppercents == NULL)
+ return -1;
+ }
+ }
+
next = disasm__get_next_ip_line(&notes->src->source, dl);

disasm__calc_percent(sym, evsel, offset,
next ? next->offset : (s64) len,
- &path, &percent);
+ &path, ppercents, nr_percents);
+
+ for (i = 0; i < nr_percents; i++) {
+ percent = ppercents[i];
+
+ if (percent > percent_max)
+ percent_max = percent;
+ }

- if (percent < min_pcnt)
+ if (percent_max < min_pcnt)
return -1;

if (max_lines && printed >= max_lines)
@@ -704,7 +731,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
}
}

- color = get_percent_color(percent);
+ color = get_percent_color(percent_max);

/*
* Also color the filename and line if needed, with
@@ -720,20 +747,35 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
}
}

- color_fprintf(stdout, color, " %7.2f", percent);
+ for (i = 0; i < nr_percents; i++) {
+ percent = ppercents[i];
+ color = get_percent_color(percent);
+ color_fprintf(stdout, color, " %7.2f", percent);
+ }
+
printf(" : ");
color_fprintf(stdout, PERF_COLOR_MAGENTA, " %" PRIx64 ":", addr);
color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", dl->line);
+
+ if (ppercents != &percent)
+ free(ppercents);
} else if (max_lines && printed >= max_lines)
return 1;
else {
+ int width = 8;
+
if (queue)
return -1;

+ if (symbol_conf.event_group) {
+ if (perf_evsel__is_group_leader(evsel))
+ width *= evsel->nr_members + 1;
+ }
+
if (!*dl->line)
- printf(" :\n");
+ printf(" %*s:\n", width, " ");
else
- printf(" : %s\n", dl->line);
+ printf(" %*s: %s\n", width, " ", dl->line);
}

return 0;
@@ -1096,6 +1138,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
int printed = 2, queue_len = 0;
int more = 0;
u64 len;
+ int width = 8;
+ int namelen;

filename = strdup(dso->long_name);
if (!filename)
@@ -1108,8 +1152,16 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,

len = symbol__size(sym);

- printf(" Percent | Source code & Disassembly of %s\n", d_filename);
- printf("------------------------------------------------\n");
+ if (symbol_conf.event_group) {
+ if (perf_evsel__is_group_leader(evsel))
+ width *= evsel->nr_members + 1;
+ }
+ namelen = strlen(d_filename);
+
+ printf(" %-*.*s| Source code & Disassembly of %s\n",
+ width, width, "Percent", d_filename);
+ printf("-%-*.*s-------------------------------------\n",
+ width + namelen, width + namelen, graph_dotted_line);

if (verbose)
symbol__annotate_hits(sym, evsel);
--
1.7.9.2

2012-11-09 17:30:51

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 05/13] perf annotate: Pass evsel instead of evidx on annotation functions

From: Namhyung Kim <[email protected]>

Pass evsel instead of evidx. This is a preparation for supporting
event group view in annotation and no functional change is intended.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/builtin-annotate.c | 14 ++++++++------
tools/perf/builtin-top.c | 2 +-
tools/perf/ui/browsers/annotate.c | 30 +++++++++++++++++-------------
tools/perf/ui/browsers/hists.c | 2 +-
tools/perf/util/annotate.c | 33 ++++++++++++++++++---------------
tools/perf/util/annotate.h | 17 +++++++++--------
tools/perf/util/hist.h | 5 +++--
7 files changed, 57 insertions(+), 46 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index dc870cf31b79..0c6edd60d67e 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -108,14 +108,16 @@ static int process_sample_event(struct perf_tool *tool,
return 0;
}

-static int hist_entry__tty_annotate(struct hist_entry *he, int evidx,
+static int hist_entry__tty_annotate(struct hist_entry *he,
+ struct perf_evsel *evsel,
struct perf_annotate *ann)
{
- return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx,
+ return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel,
ann->print_line, ann->full_paths, 0, 0);
}

-static void hists__find_annotations(struct hists *self, int evidx,
+static void hists__find_annotations(struct hists *self,
+ struct perf_evsel *evsel,
struct perf_annotate *ann)
{
struct rb_node *nd = rb_first(&self->entries), *next;
@@ -139,7 +141,7 @@ find_next:
}

if (use_browser > 0) {
- key = hist_entry__tui_annotate(he, evidx, NULL);
+ key = hist_entry__tui_annotate(he, evsel, NULL);
switch (key) {
case K_RIGHT:
next = rb_next(nd);
@@ -154,7 +156,7 @@ find_next:
if (next != NULL)
nd = next;
} else {
- hist_entry__tty_annotate(he, evidx, ann);
+ hist_entry__tty_annotate(he, evsel, ann);
nd = rb_next(nd);
/*
* Since we have a hist_entry per IP for the same
@@ -216,7 +218,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
total_nr_samples += nr_samples;
hists__collapse_resort(hists);
hists__output_resort(hists);
- hists__find_annotations(hists, pos->idx, ann);
+ hists__find_annotations(hists, pos, ann);
}
}

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c9ff3950cd4b..16d5ef1bd1b9 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -251,7 +251,7 @@ static void perf_top__show_details(struct perf_top *top)
printf("Showing %s for %s\n", perf_evsel__name(top->sym_evsel), symbol->name);
printf(" Events Pcnt (>=%d%%)\n", top->sym_pcnt_filter);

- more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel->idx,
+ more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel,
0, top->sym_pcnt_filter, top->print_entries, 4);
if (top->zero)
symbol__annotate_zero_histogram(symbol, top->sym_evsel->idx);
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index bb393dd26ba2..ad943164ece9 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -8,6 +8,7 @@
#include "../../util/hist.h"
#include "../../util/sort.h"
#include "../../util/symbol.h"
+#include "../../util/evsel.h"
#include <pthread.h>
#include <newt.h>

@@ -324,7 +325,7 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser,
}

static void annotate_browser__calc_percent(struct annotate_browser *browser,
- int evidx)
+ struct perf_evsel *evsel)
{
struct map_symbol *ms = browser->b.priv;
struct symbol *sym = ms->sym;
@@ -337,7 +338,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,

list_for_each_entry(pos, &notes->src->source, node) {
struct browser_disasm_line *bpos = disasm_line__browser(pos);
- bpos->percent = disasm_line__calc_percent(pos, sym, evidx);
+ bpos->percent = disasm_line__calc_percent(pos, sym, evsel->idx);
if (bpos->percent < 0.01) {
RB_CLEAR_NODE(&bpos->rb_node);
continue;
@@ -394,7 +395,8 @@ static void annotate_browser__init_asm_mode(struct annotate_browser *browser)
browser->b.nr_entries = browser->nr_asm_entries;
}

-static bool annotate_browser__callq(struct annotate_browser *browser, int evidx,
+static bool annotate_browser__callq(struct annotate_browser *browser,
+ struct perf_evsel *evsel,
struct hist_browser_timer *hbt)
{
struct map_symbol *ms = browser->b.priv;
@@ -425,7 +427,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser, int evidx,
}

pthread_mutex_unlock(&notes->lock);
- symbol__tui_annotate(target, ms->map, evidx, hbt);
+ symbol__tui_annotate(target, ms->map, evsel, hbt);
ui_browser__show_title(&browser->b, sym->name);
return true;
}
@@ -608,7 +610,8 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser
browser->addr_width += browser->jumps_width + 1;
}

-static int annotate_browser__run(struct annotate_browser *browser, int evidx,
+static int annotate_browser__run(struct annotate_browser *browser,
+ struct perf_evsel *evsel,
struct hist_browser_timer *hbt)
{
struct rb_node *nd = NULL;
@@ -621,7 +624,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,
if (ui_browser__show(&browser->b, sym->name, help) < 0)
return -1;

- annotate_browser__calc_percent(browser, evidx);
+ annotate_browser__calc_percent(browser, evsel);

if (browser->curr_hot) {
annotate_browser__set_rb_top(browser, browser->curr_hot);
@@ -634,7 +637,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,
key = ui_browser__run(&browser->b, delay_secs);

if (delay_secs != 0) {
- annotate_browser__calc_percent(browser, evidx);
+ annotate_browser__calc_percent(browser, evsel);
/*
* Current line focus got out of the list of most active
* lines, NULL it so that if TAB|UNTAB is pressed, we
@@ -650,7 +653,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,
hbt->timer(hbt->arg);

if (delay_secs != 0)
- symbol__annotate_decay_histogram(sym, evidx);
+ symbol__annotate_decay_histogram(sym, evsel->idx);
continue;
case K_TAB:
if (nd != NULL) {
@@ -747,7 +750,7 @@ show_help:
goto show_sup_ins;
goto out;
} else if (!(annotate_browser__jump(browser) ||
- annotate_browser__callq(browser, evidx, hbt))) {
+ annotate_browser__callq(browser, evsel, hbt))) {
show_sup_ins:
ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions.");
}
@@ -769,10 +772,10 @@ out:
return key;
}

-int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
+int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
struct hist_browser_timer *hbt)
{
- return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, hbt);
+ return symbol__tui_annotate(he->ms.sym, he->ms.map, evsel, hbt);
}

static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
@@ -827,7 +830,8 @@ static inline int width_jumps(int n)
return 1;
}

-int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
+int symbol__tui_annotate(struct symbol *sym, struct map *map,
+ struct perf_evsel *evsel,
struct hist_browser_timer *hbt)
{
struct disasm_line *pos, *n;
@@ -910,7 +914,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,

annotate_browser__update_addr_width(&browser);

- ret = annotate_browser__run(&browser, evidx, hbt);
+ ret = annotate_browser__run(&browser, evsel, hbt);
list_for_each_entry_safe(pos, n, &notes->src->source, node) {
list_del(&pos->node);
disasm_line__free(pos);
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 893c07f172f5..a1229a449fa5 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1439,7 +1439,7 @@ do_annotate:
* Don't let this be freed, say, by hists__decay_entry.
*/
he->used = true;
- err = hist_entry__tui_annotate(he, evsel->idx, hbt);
+ err = hist_entry__tui_annotate(he, evsel, hbt);
he->used = false;
/*
* offer option to annotate the other branch source or target
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 0ac9cc4c5e7d..3a088a367c52 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -14,6 +14,7 @@
#include "symbol.h"
#include "debug.h"
#include "annotate.h"
+#include "evsel.h"
#include <pthread.h>
#include <linux/bitops.h>

@@ -635,7 +636,7 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa
}

static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 start,
- int evidx, u64 len, int min_pcnt, int printed,
+ struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
int max_lines, struct disasm_line *queue)
{
static const char *prev_line;
@@ -648,7 +649,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
const char *color;
struct annotation *notes = symbol__annotation(sym);
struct source_line *src_line = notes->src->lines;
- struct sym_hist *h = annotation__histogram(notes, evidx);
+ struct sym_hist *h = annotation__histogram(notes, evsel->idx);
s64 offset = dl->offset;
const u64 addr = start + offset;
struct disasm_line *next;
@@ -680,7 +681,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
list_for_each_entry_from(queue, &notes->src->source, node) {
if (queue == dl)
break;
- disasm_line__print(queue, sym, start, evidx, len,
+ disasm_line__print(queue, sym, start, evsel, len,
0, 0, 1, NULL);
}
}
@@ -967,7 +968,8 @@ 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,
- int evidx, struct rb_root *root, int len,
+ struct perf_evsel *evsel,
+ struct rb_root *root, int len,
const char *filename)
{
u64 start;
@@ -975,7 +977,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
char cmd[PATH_MAX * 2];
struct source_line *src_line;
struct annotation *notes = symbol__annotation(sym);
- struct sym_hist *h = annotation__histogram(notes, evidx);
+ struct sym_hist *h = annotation__histogram(notes, evsel->idx);
struct rb_root tmp_root = RB_ROOT;

if (!h->sum)
@@ -1050,10 +1052,10 @@ static void print_summary(struct rb_root *root, const char *filename)
}
}

-static void symbol__annotate_hits(struct symbol *sym, int evidx)
+static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
{
struct annotation *notes = symbol__annotation(sym);
- struct sym_hist *h = annotation__histogram(notes, evidx);
+ struct sym_hist *h = annotation__histogram(notes, evsel->idx);
u64 len = symbol__size(sym), offset;

for (offset = 0; offset < len; ++offset)
@@ -1063,9 +1065,9 @@ static void symbol__annotate_hits(struct symbol *sym, int evidx)
printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
}

-int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
- bool full_paths, int min_pcnt, int max_lines,
- int context)
+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)
{
struct dso *dso = map->dso;
char *filename;
@@ -1092,7 +1094,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
printf("------------------------------------------------\n");

if (verbose)
- symbol__annotate_hits(sym, evidx);
+ symbol__annotate_hits(sym, evsel);

list_for_each_entry(pos, &notes->src->source, node) {
if (context && queue == NULL) {
@@ -1100,7 +1102,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
queue_len = 0;
}

- switch (disasm_line__print(pos, sym, start, evidx, len,
+ switch (disasm_line__print(pos, sym, start, evsel, len,
min_pcnt, printed, max_lines,
queue)) {
case 0:
@@ -1195,7 +1197,8 @@ size_t disasm__fprintf(struct list_head *head, FILE *fp)
return printed;
}

-int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
+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)
{
@@ -1210,12 +1213,12 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
len = symbol__size(sym);

if (print_lines) {
- symbol__get_source_line(sym, map, evidx, &source_line,
+ symbol__get_source_line(sym, map, evsel, &source_line,
len, filename);
print_summary(&source_line, filename);
}

- symbol__annotate_printf(sym, map, evidx, full_paths,
+ symbol__annotate_printf(sym, map, evsel, full_paths,
min_pcnt, max_lines, 0);
if (print_lines)
symbol__free_source_line(sym, len);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 8eec94358a4a..5ce9ff3ffcd7 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -129,24 +129,25 @@ void symbol__annotate_zero_histograms(struct symbol *sym);

int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym);
-int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
- bool full_paths, int min_pcnt, int max_lines,
- int context);
+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);
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);

-int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
- bool print_lines, bool full_paths, int min_pcnt,
- int max_lines);
+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);

#ifdef NEWT_SUPPORT
-int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
+int symbol__tui_annotate(struct symbol *sym, struct map *map,
+ struct perf_evsel *evsel,
struct hist_browser_timer *hbt);
#else
static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
struct map *map __maybe_unused,
- int evidx __maybe_unused,
+ struct perf_evsel *evsel __maybe_unused,
struct hist_browser_timer *hbt
__maybe_unused)
{
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 99ac4d34c917..71035cea22ae 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -167,7 +167,7 @@ struct hist_browser_timer {

#ifdef NEWT_SUPPORT
#include "../ui/keysyms.h"
-int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
+int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
struct hist_browser_timer *hbt);

int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
@@ -186,7 +186,8 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,

static inline int hist_entry__tui_annotate(struct hist_entry *self
__maybe_unused,
- int evidx __maybe_unused,
+ struct perf_evsel *evsel
+ __maybe_unused,
struct hist_browser_timer *hbt
__maybe_unused)
{
--
1.7.9.2

2012-11-09 17:31:21

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 03/13] perf annotate: Merge same lines in summary view

From: Namhyung Kim <[email protected]>

The --print-line option of perf annotate command shows summary for
each source line. But it didn't merge same lines so that it can
appear multiple times.

* before:

Sorted summary for file /home/namhyung/bin/mcol
----------------------------------------------
21.71 /home/namhyung/tmp/mcol.c:26
20.66 /home/namhyung/tmp/mcol.c:25
9.53 /home/namhyung/tmp/mcol.c:24
7.68 /home/namhyung/tmp/mcol.c:25
7.67 /home/namhyung/tmp/mcol.c:25
7.66 /home/namhyung/tmp/mcol.c:26
7.49 /home/namhyung/tmp/mcol.c:26
6.92 /home/namhyung/tmp/mcol.c:25
6.81 /home/namhyung/tmp/mcol.c:25
1.07 /home/namhyung/tmp/mcol.c:26
0.52 /home/namhyung/tmp/mcol.c:25
0.51 /home/namhyung/tmp/mcol.c:25
0.51 /home/namhyung/tmp/mcol.c:24

* after:

Sorted summary for file /home/namhyung/bin/mcol
----------------------------------------------
50.77 /home/namhyung/tmp/mcol.c:25
37.94 /home/namhyung/tmp/mcol.c:26
10.04 /home/namhyung/tmp/mcol.c:24

To do that, introduce percent_sum field so that the normal
line-by-line output doesn't get changed.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/util/annotate.c | 55 +++++++++++++++++++++++++++++++++++++++++---
tools/perf/util/annotate.h | 1 +
2 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 12287b121669..0ac9cc4c5e7d 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -890,12 +890,41 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
struct source_line *iter;
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
+ int ret;

while (*p != NULL) {
parent = *p;
iter = rb_entry(parent, struct source_line, node);

- if (src_line->percent > iter->percent)
+ ret = strcmp(iter->path, src_line->path);
+ if (ret == 0) {
+ iter->percent_sum += src_line->percent;
+ return;
+ }
+
+ if (ret < 0)
+ p = &(*p)->rb_left;
+ else
+ p = &(*p)->rb_right;
+ }
+
+ src_line->percent_sum = src_line->percent;
+
+ rb_link_node(&src_line->node, parent, p);
+ rb_insert_color(&src_line->node, root);
+}
+
+static void __resort_source_line(struct rb_root *root, struct source_line *src_line)
+{
+ struct source_line *iter;
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+
+ while (*p != NULL) {
+ parent = *p;
+ iter = rb_entry(parent, struct source_line, node);
+
+ if (src_line->percent_sum > iter->percent_sum)
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
@@ -905,6 +934,24 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
rb_insert_color(&src_line->node, root);
}

+static void resort_source_line(struct rb_root *dest_root, struct rb_root *src_root)
+{
+ struct source_line *src_line;
+ struct rb_node *node;
+
+ node = rb_first(src_root);
+ while (node) {
+ struct rb_node *next;
+
+ src_line = rb_entry(node, struct source_line, node);
+ next = rb_next(node);
+ rb_erase(node, src_root);
+
+ __resort_source_line(dest_root, src_line);
+ node = next;
+ }
+}
+
static void symbol__free_source_line(struct symbol *sym, int len)
{
struct annotation *notes = symbol__annotation(sym);
@@ -929,6 +976,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
struct source_line *src_line;
struct annotation *notes = symbol__annotation(sym);
struct sym_hist *h = annotation__histogram(notes, evidx);
+ struct rb_root tmp_root = RB_ROOT;

if (!h->sum)
return 0;
@@ -963,12 +1011,13 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
goto next;

strcpy(src_line[i].path, path);
- insert_source_line(root, &src_line[i]);
+ insert_source_line(&tmp_root, &src_line[i]);

next:
pclose(fp);
}

+ resort_source_line(root, &tmp_root);
return 0;
}

@@ -992,7 +1041,7 @@ static void print_summary(struct rb_root *root, const char *filename)
char *path;

src_line = rb_entry(node, struct source_line, node);
- percent = src_line->percent;
+ percent = src_line->percent_sum;
color = get_percent_color(percent);
path = src_line->path;

diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index c6272011625a..8eec94358a4a 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -76,6 +76,7 @@ struct sym_hist {
struct source_line {
struct rb_node node;
double percent;
+ double percent_sum;
char *path;
};

--
1.7.9.2

2012-11-14 07:42:28

by Namhyung Kim

[permalink] [raw]
Subject: [tip:perf/core] perf annotate: Whitespace fixups

Commit-ID: 2ba34aaa6db8b61cf1fa14132f885ba6bc7c9ae0
Gitweb: http://git.kernel.org/tip/2ba34aaa6db8b61cf1fa14132f885ba6bc7c9ae0
Author: Namhyung Kim <[email protected]>
AuthorDate: Sat, 10 Nov 2012 02:27:13 +0900
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Fri, 9 Nov 2012 16:22:46 -0300

perf annotate: Whitespace fixups

Some lines are indented by whitespace characters rather than tabs. Fix
them.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/annotate.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index b14d4df..435bf6d 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -171,15 +171,15 @@ static int lock__parse(struct ins_operands *ops)
if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
goto out_free_ops;

- ops->locked.ins = ins__find(name);
- if (ops->locked.ins == NULL)
- goto out_free_ops;
+ ops->locked.ins = ins__find(name);
+ if (ops->locked.ins == NULL)
+ goto out_free_ops;

- if (!ops->locked.ins->ops)
- return 0;
+ if (!ops->locked.ins->ops)
+ return 0;

- if (ops->locked.ins->ops->parse)
- ops->locked.ins->ops->parse(ops->locked.ops);
+ if (ops->locked.ins->ops->parse)
+ ops->locked.ins->ops->parse(ops->locked.ops);

return 0;

2012-11-14 07:43:31

by Namhyung Kim

[permalink] [raw]
Subject: [tip:perf/core] perf annotate: Don' t try to follow jump target on PLT symbols

Commit-ID: 32ae1efd9d40645601cd4e09fa83a2711dd1ad6d
Gitweb: http://git.kernel.org/tip/32ae1efd9d40645601cd4e09fa83a2711dd1ad6d
Author: Namhyung Kim <[email protected]>
AuthorDate: Sat, 10 Nov 2012 02:27:15 +0900
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Fri, 9 Nov 2012 16:23:21 -0300

perf annotate: Don't try to follow jump target on PLT symbols

The perf annotate browser on TUI can identify a jump target for a
selected instruction. It assumes that the jump target is within the
function but it's not the case of PLT symbols which have offset out of
the function as a target.

Since it caused a segmentation fault, do not try to follow jump target
on the PLT symbols.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/ui/browsers/annotate.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 3eff17f..5dab3ca 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -188,6 +188,12 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
struct disasm_line *cursor = ab->selection, *target;
struct browser_disasm_line *btarget, *bcursor;
unsigned int from, to;
+ struct map_symbol *ms = ab->b.priv;
+ struct symbol *sym = ms->sym;
+
+ /* PLT symbols contain external offsets */
+ if (strstr(sym->name, "@plt"))
+ return;

if (!cursor || !cursor->ins || !ins__is_jump(cursor->ins) ||
!disasm_line__has_offset(cursor))
@@ -771,6 +777,12 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browser
size_t size)
{
u64 offset;
+ struct map_symbol *ms = browser->b.priv;
+ struct symbol *sym = ms->sym;
+
+ /* PLT symbols contain external offsets */
+ if (strstr(sym->name, "@plt"))
+ return;

for (offset = 0; offset < size; ++offset) {
struct disasm_line *dl = browser->offsets[offset], *dlt;