perf annotate: Parse --asm-raw output properly
Namhyung Kim
maintainerPATCH 1/3 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.
--- tools/perf/ui/browsers/annotate.c | 2 ++ tools/perf/util/annotate.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+)
tools/perf/ui/browsers/annotate.c +2 -0
@@ -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 ;
tools/perf/util/annotate.c +29 -0
@@ -492,6 +492,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 +517,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 ]))
Signature · 1 line
1.7.11.7
Namhyung Kim
maintainerPATCH 2/3 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
----------------------------------------------
24.40 /home/namhyung/tmp/mcol.c:26
21.58 /home/namhyung/tmp/mcol.c:25
10.14 /home/namhyung/tmp/mcol.c:24
8.59 /home/namhyung/tmp/mcol.c:25
8.57 /home/namhyung/tmp/mcol.c:25
8.42 /home/namhyung/tmp/mcol.c:26
8.31 /home/namhyung/tmp/mcol.c:26
8.30 /home/namhyung/tmp/mcol.c:25
0.80 /home/namhyung/tmp/mcol.c:26* after:
Sorted summary for file /home/namhyung/bin/mcol
----------------------------------------------
41.93 /home/namhyung/tmp/mcol.c:26 10.14 /home/namhyung/tmp/mcol.c:24 47.04 /home/namhyung/tmp/mcol.c:25
To do that, introduce percent_sum field so that the normal line-by-line output doesn't get changed.
--- tools/perf/util/annotate.c | 53 ++++++++++++++++++++++++++++++++++++++++++++-- tools/perf/util/annotate.h | 1 + 2 files changed, 52 insertions(+), 2 deletions(-)
tools/perf/util/annotate.c +51 -2
@@ -887,6 +887,35 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_linstruct 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); + + 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;
@@ -902,6 +931,24 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_linrb_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);
@@ -926,6 +973,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 ;
@@ -960,12 +1008,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 ; }
@@ -989,7 +1038,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;
tools/perf/util/annotate.h +1 -0
@@ -76,6 +76,7 @@ struct sym_hist {struct source_line {struct rb_node node;double percent; +double percent_sum;char *path; };
Signature · 1 line
1.7.11.7
Namhyung Kim
maintainerPATCH v2 2/3 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
----------------------------------------------
24.40 /home/namhyung/tmp/mcol.c:26
21.58 /home/namhyung/tmp/mcol.c:25
10.14 /home/namhyung/tmp/mcol.c:24
8.59 /home/namhyung/tmp/mcol.c:25
8.57 /home/namhyung/tmp/mcol.c:25
8.42 /home/namhyung/tmp/mcol.c:26
8.31 /home/namhyung/tmp/mcol.c:26
8.30 /home/namhyung/tmp/mcol.c:25
0.80 /home/namhyung/tmp/mcol.c:26* after:
Sorted summary for file /home/namhyung/bin/mcol
----------------------------------------------
41.93 /home/namhyung/tmp/mcol.c:26 10.14 /home/namhyung/tmp/mcol.c:24 47.04 /home/namhyung/tmp/mcol.c:25
To do that, introduce percent_sum field so that the normal line-by-line output doesn't get changed.
---
* v2: ->percent_sum should be used when resorting.
tools/perf/util/annotate.c | 55 +++++++++++++++++++++++++++++++++++++++++++--- tools/perf/util/annotate.h | 1 + 2 files changed, 53 insertions(+), 3 deletions(-)
tools/perf/util/annotate.c +52 -3
@@ -887,12 +887,41 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_linstruct 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;
@@ -902,6 +931,24 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_linrb_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);
@@ -926,6 +973,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 ;
@@ -960,12 +1008,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 ; }
@@ -989,7 +1038,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;
tools/perf/util/annotate.h +1 -0
@@ -76,6 +76,7 @@ struct sym_hist {struct source_line {struct rb_node node;double percent; +double percent_sum;char *path; };
Signature · 1 line
1.7.11.7
Namhyung Kim
maintainerPATCH v3 2/3 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.
---
* v3: Renew output in changelog
* v2: ->percent_sum should be used when resorting.
tools/perf/util/annotate.c | 55 +++++++++++++++++++++++++++++++++++++++++++--- tools/perf/util/annotate.h | 1 + 2 files changed, 53 insertions(+), 3 deletions(-)
tools/perf/util/annotate.c +52 -3
@@ -887,12 +887,41 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_linstruct 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;
@@ -902,6 +931,24 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_linrb_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);
@@ -926,6 +973,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 ;
@@ -960,12 +1008,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 ; }
@@ -989,7 +1038,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;
tools/perf/util/annotate.h +1 -0
@@ -76,6 +76,7 @@ struct sym_hist {struct source_line {struct rb_node node;double percent; +double percent_sum;char *path; };
Signature · 1 line
1.7.11.7
[tip:perf/core] perf annotate: Merge same lines in summary view
Commit-ID: 411279658adf6a4f5bb25ec032a39ae905bcf234 Gitweb: http://git.kernel.org/tip/411279658adf6a4f5bb25ec032a39ae905bcf234 Author: Namhyung Kim <[email protected]> AuthorDate: Fri, 9 Nov 2012 14:58:49 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 9 Nov 2012 16:50:18 -0300
perf annotate: Merge same lines in summary view
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:24To do that, introduce percent_sum field so that the normal line-by-line output doesn't get changed.
--- tools/perf/util/annotate.c | 55 +++++++++++++++++++++++++++++++++++++++++-- tools/perf/util/annotate.h | 1 + 2 files changed, 53 insertions(+), 3 deletions(-)
tools/perf/util/annotate.c +52 -3
@@ -858,12 +858,41 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_linstruct 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;
@@ -873,6 +902,24 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_linrb_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);
@@ -897,6 +944,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 ;
@@ -931,12 +979,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 ; }
@@ -960,7 +1009,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;
tools/perf/util/annotate.h +1 -0
@@ -76,6 +76,7 @@ struct sym_hist {struct source_line {struct rb_node node;double percent; +double percent_sum;char *path; };
Namhyung Kim
maintainerPATCH 3/3 perf annotate: Don't try to follow jump target on PLT symbols
In reply to Namhyung KimFrom: 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.
--- tools/perf/ui/browsers/annotate.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
tools/perf/ui/browsers/annotate.c +12 -0
@@ -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;
Signature · 1 line
1.7.11.7