Commit 1fa2e84d authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-annotate-for-mingo' of...

Merge tag 'perf-annotate-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Annotation improvements:

Now the default annotate browser uses a much more compact format, implementing
suggestions made made by several people, notably Linus.

Here is part of the new __list_del_entry() annotation:

__list_del_entry
    8.47 │      push   %rbp
    8.47 │      mov    (%rdi),%rdx
   20.34 │      mov    $0xdead000000100100,%rcx
    3.39 │      mov    0x8(%rdi),%rax
    0.00 │      mov    %rsp,%rbp
    1.69 │      cmp    %rcx,%rdx
    0.00 │      je     43
    1.69 │      mov    $0xdead000000200200,%rcx
    3.39 │      cmp    %rcx,%rax
    0.00 │      je     a3
    5.08 │      mov    (%rax),%r8
   18.64 │      cmp    %r8,%rdi
    0.00 │      jne    84
    1.69 │      mov    0x8(%rdx),%r8
   25.42 │      cmp    %r8,%rdi
    0.00 │      jne    65
    1.69 │      mov    %rax,0x8(%rdx)
    0.00 │      mov    %rdx,(%rax)
    0.00 │      leaveq
    0.00 │      retq
    0.00 │ 43:  mov    %rdx,%r8
    0.00 │      mov    %rdi,%rcx
    0.00 │      mov    $0xffffffff817cd6a8,%rdx
    0.00 │      mov    $0x31,%esi
    0.00 │      mov    $0xffffffff817cd6e0,%rdi
    0.00 │      xor    %eax,%eax
    0.00 │      callq  ffffffff8104eab0 <warn_slowpath_fmt>
    0.00 │      leaveq
    0.00 │      retq
    0.00 │ 65:  mov    %rdi,%rcx
    0.00 │      mov    $0xffffffff817cd780,%rdx
    0.00 │      mov    $0x3a,%esi
    0.00 │      mov    $0xffffffff817cd6e0,%rdi
    0.00 │      xor    %eax,%eax
    0.00 │      callq  ffffffff8104eab0 <warn_slowpath_fmt>
    0.00 │      leaveq
    0.00 │      retq

The infrastructure is there to provide formatters for any instruction,
like the one I'll do for call functions to elide the address.

Further fixes on top of the first iteration:

- Sometimes a jump points to an offset with no instructions, make the
  mark jump targets function handle that, for now just ignoring such
  jump targets, more investigation is needed to figure out how to cope
  with that.

- Handle jump targets that are outside the function, for now just don't
  try to draw the connector arrow, right thing seems to be to mark this
  jump with a -> (right arrow) and handle it like a callq.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 392d65a9 38b31bd0
...@@ -593,6 +593,52 @@ unsigned int ui_browser__argv_refresh(struct ui_browser *browser) ...@@ -593,6 +593,52 @@ unsigned int ui_browser__argv_refresh(struct ui_browser *browser)
return row; return row;
} }
void ui_browser__write_graph(struct ui_browser *browser __used, int graph)
{
SLsmg_set_char_set(1);
SLsmg_write_char(graph);
SLsmg_set_char_set(0);
}
void __ui_browser__line_arrow_up(struct ui_browser *browser, unsigned int column,
u64 start, u64 end, int start_width)
{
unsigned int row, end_row;
SLsmg_set_char_set(1);
if (start < browser->top_idx + browser->height) {
row = start - browser->top_idx;
ui_browser__gotorc(browser, row, column);
SLsmg_write_char(SLSMG_LLCORN_CHAR);
ui_browser__gotorc(browser, row, column + 1);
SLsmg_draw_hline(start_width);
if (row-- == 0)
goto out;
} else
row = browser->height - 1;
if (end > browser->top_idx)
end_row = end - browser->top_idx;
else
end_row = 0;
ui_browser__gotorc(browser, end_row, column);
SLsmg_draw_vline(row - end_row + 1);
ui_browser__gotorc(browser, end_row, column);
if (end >= browser->top_idx) {
SLsmg_write_char(SLSMG_ULCORN_CHAR);
ui_browser__gotorc(browser, end_row, column + 1);
SLsmg_write_char(SLSMG_HLINE_CHAR);
ui_browser__gotorc(browser, end_row, column + 2);
SLsmg_write_char(SLSMG_RARROW_CHAR);
}
out:
SLsmg_set_char_set(0);
}
void ui_browser__init(void) void ui_browser__init(void)
{ {
int i = 0; int i = 0;
......
...@@ -37,6 +37,9 @@ void ui_browser__refresh_dimensions(struct ui_browser *self); ...@@ -37,6 +37,9 @@ void ui_browser__refresh_dimensions(struct ui_browser *self);
void ui_browser__reset_index(struct ui_browser *self); void ui_browser__reset_index(struct ui_browser *self);
void ui_browser__gotorc(struct ui_browser *self, int y, int x); void ui_browser__gotorc(struct ui_browser *self, int y, int x);
void ui_browser__write_graph(struct ui_browser *browser, int graph);
void __ui_browser__line_arrow_up(struct ui_browser *browser, unsigned int column,
u64 start, u64 end, int start_width);
void __ui_browser__show_title(struct ui_browser *browser, const char *title); void __ui_browser__show_title(struct ui_browser *browser, const char *title);
void ui_browser__show_title(struct ui_browser *browser, const char *title); void ui_browser__show_title(struct ui_browser *browser, const char *title);
int ui_browser__show(struct ui_browser *self, const char *title, int ui_browser__show(struct ui_browser *self, const char *title,
......
This diff is collapsed.
This diff is collapsed.
...@@ -2,20 +2,54 @@ ...@@ -2,20 +2,54 @@
#define __PERF_ANNOTATE_H #define __PERF_ANNOTATE_H
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include "types.h" #include "types.h"
#include "symbol.h" #include "symbol.h"
#include <linux/list.h> #include <linux/list.h>
#include <linux/rbtree.h> #include <linux/rbtree.h>
struct objdump_line { struct ins;
struct list_head node;
s64 offset; struct ins_operands {
char *line; char *raw;
struct {
char *name;
u64 offset;
u64 addr;
} target;
};
struct ins_ops {
int (*parse)(struct ins_operands *ops);
int (*scnprintf)(struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, bool addrs);
}; };
void objdump_line__free(struct objdump_line *self); struct ins {
struct objdump_line *objdump__get_next_ip_line(struct list_head *head, const char *name;
struct objdump_line *pos); struct ins_ops *ops;
};
bool ins__is_jump(const struct ins *ins);
bool ins__is_call(const struct ins *ins);
struct disasm_line {
struct list_head node;
s64 offset;
char *line;
char *name;
struct ins *ins;
struct ins_operands ops;
};
static inline bool disasm_line__has_offset(const struct disasm_line *dl)
{
return dl->ops.target.offset != UINT64_MAX;
}
void disasm_line__free(struct disasm_line *dl);
struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos);
size_t disasm__fprintf(struct list_head *head, FILE *fp);
struct sym_hist { struct sym_hist {
u64 sum; u64 sum;
...@@ -32,7 +66,7 @@ struct source_line { ...@@ -32,7 +66,7 @@ struct source_line {
* *
* @histogram: Array of addr hit histograms per event being monitored * @histogram: Array of addr hit histograms per event being monitored
* @lines: If 'print_lines' is specified, per source code line percentages * @lines: If 'print_lines' is specified, per source code line percentages
* @source: source parsed from objdump -dS * @source: source parsed from a disassembler like objdump -dS
* *
* lines is allocated, percentages calculated and all sorted by percentage * lines is allocated, percentages calculated and all sorted by percentage
* when the annotation is about to be presented, so the percentages are for * when the annotation is about to be presented, so the percentages are for
...@@ -82,7 +116,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, ...@@ -82,7 +116,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
int context); int context);
void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
void objdump_line_list__purge(struct list_head *head); void disasm__purge(struct list_head *head);
int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
bool print_lines, bool full_paths, int min_pcnt, bool print_lines, bool full_paths, int min_pcnt,
......
...@@ -65,6 +65,11 @@ struct symbol { ...@@ -65,6 +65,11 @@ struct symbol {
void symbol__delete(struct symbol *sym); void symbol__delete(struct symbol *sym);
static inline size_t symbol__size(const struct symbol *sym)
{
return sym->end - sym->start + 1;
}
struct strlist; struct strlist;
struct symbol_conf { struct symbol_conf {
......
...@@ -148,3 +148,13 @@ int readn(int fd, void *buf, size_t n) ...@@ -148,3 +148,13 @@ int readn(int fd, void *buf, size_t n)
return buf - buf_start; return buf - buf_start;
} }
size_t hex_width(u64 v)
{
size_t n = 1;
while ((v >>= 4))
++n;
return n;
}
...@@ -265,4 +265,6 @@ bool is_power_of_2(unsigned long n) ...@@ -265,4 +265,6 @@ bool is_power_of_2(unsigned long n)
return (n != 0 && ((n & (n - 1)) == 0)); return (n != 0 && ((n & (n - 1)) == 0));
} }
size_t hex_width(u64 v);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment