summaryrefslogtreecommitdiff
path: root/tools/bpf/bpftool/xlated_dumper.c
diff options
context:
space:
mode:
authorJiong Wang <jiong.wang@netronome.com>2018-03-02 05:01:21 +0300
committerAlexei Starovoitov <ast@kernel.org>2018-03-02 05:29:49 +0300
commitefcef17a6d6575dacca22bce69e139354c5a2170 (patch)
tree2305cd907b66788820d35647f7ef39392550319a /tools/bpf/bpftool/xlated_dumper.c
parent6e9eb7e3f8705e5e3f1a6a2b47450ec606ab012b (diff)
downloadlinux-efcef17a6d6575dacca22bce69e139354c5a2170.tar.xz
tools: bpftool: generate .dot graph from CFG information
This patch let bpftool print .dot graph file into stdout. This graph is generated by the following steps: - iterate through the function list. - generate basic-block(BB) definition for each BB in the function. - draw out edges to connect BBs. This patch is the initial support, the layout and decoration of the .dot graph could be improved. Also, it will be useful if we could visualize some performance data from static analysis. Signed-off-by: Jiong Wang <jiong.wang@netronome.com> Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/bpf/bpftool/xlated_dumper.c')
-rw-r--r--tools/bpf/bpftool/xlated_dumper.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/tools/bpf/bpftool/xlated_dumper.c b/tools/bpf/bpftool/xlated_dumper.c
index dfcdf794c9d1..20da835e9e38 100644
--- a/tools/bpf/bpftool/xlated_dumper.c
+++ b/tools/bpf/bpftool/xlated_dumper.c
@@ -123,6 +123,37 @@ static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...)
va_end(args);
}
+static void
+print_insn_for_graph(struct bpf_verifier_env *env, const char *fmt, ...)
+{
+ char buf[64], *p;
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ p = buf;
+ while (*p != '\0') {
+ if (*p == '\n') {
+ memmove(p + 3, p, strlen(buf) + 1 - (p - buf));
+ /* Align each instruction dump row left. */
+ *p++ = '\\';
+ *p++ = 'l';
+ /* Output multiline concatenation. */
+ *p++ = '\\';
+ } else if (*p == '<' || *p == '>' || *p == '|' || *p == '&') {
+ memmove(p + 1, p, strlen(buf) + 1 - (p - buf));
+ /* Escape special character. */
+ *p++ = '\\';
+ }
+
+ p++;
+ }
+
+ printf("%s", buf);
+}
+
static void print_insn_json(struct bpf_verifier_env *env, const char *fmt, ...)
{
unsigned int l = strlen(fmt);
@@ -284,3 +315,24 @@ void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,
}
}
}
+
+void dump_xlated_for_graph(struct dump_data *dd, void *buf_start, void *buf_end,
+ unsigned int start_idx)
+{
+ const struct bpf_insn_cbs cbs = {
+ .cb_print = print_insn_for_graph,
+ .cb_call = print_call,
+ .cb_imm = print_imm,
+ .private_data = dd,
+ };
+ struct bpf_insn *insn_start = buf_start;
+ struct bpf_insn *insn_end = buf_end;
+ struct bpf_insn *cur = insn_start;
+
+ for (; cur <= insn_end; cur++) {
+ printf("% 4d: ", (int)(cur - insn_start + start_idx));
+ print_bpf_insn(&cbs, NULL, cur, true);
+ if (cur != insn_end)
+ printf(" | ");
+ }
+}