aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2018-03-15 15:31:56 -0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2018-03-20 13:19:29 -0300
commit0db45bcfac8586c6f5b732f114f456f2f788b19f (patch)
treea3ff03c3d059fdf219c8e8b01efe96888e897853 /tools/perf/util
parentperf annotate: Move nr_jumps to struct annotation (diff)
downloadlinux-dev-0db45bcfac8586c6f5b732f114f456f2f788b19f.tar.xz
linux-dev-0db45bcfac8586c6f5b732f114f456f2f788b19f.zip
perf annotate: Move mark_jump_targets from the TUI to the annotation library
This also is not TUI specific, should be used in the upcoming --stdio2 mode. Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Jin Yao <yao.jin@linux.intel.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Wang Nan <wangnan0@huawei.com> Link: https://lkml.kernel.org/n/tip-v827xec8z3hxrmgp7bwa6ohs@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/annotate.c44
-rw-r--r--tools/perf/util/annotate.h4
2 files changed, 48 insertions, 0 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index d737c33c87d0..330275680a1a 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -2012,6 +2012,50 @@ size_t disasm__fprintf(struct list_head *head, FILE *fp)
return printed;
}
+
+bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym)
+{
+ if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) ||
+ !disasm_line__has_offset(dl) || dl->ops.target.offset < 0 ||
+ dl->ops.target.offset >= (s64)symbol__size(sym))
+ return false;
+
+ return true;
+}
+
+void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym)
+{
+ u64 offset, size = symbol__size(sym);
+
+ /* PLT symbols contain external offsets */
+ if (strstr(sym->name, "@plt"))
+ return;
+
+ for (offset = 0; offset < size; ++offset) {
+ struct annotation_line *al = notes->offsets[offset];
+ struct disasm_line *dl;
+
+ dl = disasm_line(al);
+
+ if (!disasm_line__is_valid_jump(dl, sym))
+ continue;
+
+ al = notes->offsets[dl->ops.target.offset];
+
+ /*
+ * FIXME: Oops, no jump target? Buggy disassembler? Or do we
+ * have to adjust to the previous offset?
+ */
+ if (al == NULL)
+ continue;
+
+ if (++al->jump_sources > notes->max_jump_sources)
+ notes->max_jump_sources = al->jump_sources;
+
+ ++notes->nr_jumps;
+ }
+}
+
static void annotation__calc_lines(struct annotation *notes, struct map *map,
struct rb_root *root, u64 start)
{
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 897a84712ab4..ab4a8b7710a0 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -90,6 +90,7 @@ struct annotation_line {
s64 offset;
char *line;
int line_nr;
+ int jump_sources;
float ipc;
u64 cycles;
size_t privsize;
@@ -116,6 +117,8 @@ static inline bool disasm_line__has_offset(const struct disasm_line *dl)
return dl->ops.target.offset_avail;
}
+bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym);
+
void disasm_line__free(struct disasm_line *dl);
struct annotation_line *
annotation_line__next(struct annotation_line *pos, struct list_head *head);
@@ -184,6 +187,7 @@ static inline int annotation__pcnt_width(struct annotation *notes)
}
void annotation__compute_ipc(struct annotation *notes, size_t size);
+void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym);
static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
{