diff options
author | Jakub Kicinski <jakub.kicinski@netronome.com> | 2017-10-09 13:30:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-10-10 15:30:16 -0400 |
commit | c9c35995bcf812ee8136f634c25bc6ccc3021d4c (patch) | |
tree | a27745367592357b7ff46ac3253d989f5a3e8129 /tools/bpf/bpftool/prog.c | |
parent | f4ac7e0b5cc8d16004ac57ff679266d573f30f77 (diff) |
tools: bpftool: use the kernel's instruction printer
Compile the instruction printer from kernel/bpf and use it
for disassembling "translated" eBPF code.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools/bpf/bpftool/prog.c')
-rw-r--r-- | tools/bpf/bpftool/prog.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 421ba89ce86a..9e2681c83717 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | #include <errno.h> | 36 | #include <errno.h> |
37 | #include <fcntl.h> | 37 | #include <fcntl.h> |
38 | #include <stdarg.h> | ||
38 | #include <stdio.h> | 39 | #include <stdio.h> |
39 | #include <stdlib.h> | 40 | #include <stdlib.h> |
40 | #include <string.h> | 41 | #include <string.h> |
@@ -46,6 +47,7 @@ | |||
46 | #include <bpf.h> | 47 | #include <bpf.h> |
47 | 48 | ||
48 | #include "main.h" | 49 | #include "main.h" |
50 | #include "disasm.h" | ||
49 | 51 | ||
50 | static const char * const prog_type_name[] = { | 52 | static const char * const prog_type_name[] = { |
51 | [BPF_PROG_TYPE_UNSPEC] = "unspec", | 53 | [BPF_PROG_TYPE_UNSPEC] = "unspec", |
@@ -297,11 +299,39 @@ static int do_show(int argc, char **argv) | |||
297 | return 0; | 299 | return 0; |
298 | } | 300 | } |
299 | 301 | ||
302 | static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...) | ||
303 | { | ||
304 | va_list args; | ||
305 | |||
306 | va_start(args, fmt); | ||
307 | vprintf(fmt, args); | ||
308 | va_end(args); | ||
309 | } | ||
310 | |||
311 | static void dump_xlated(void *buf, unsigned int len, bool opcodes) | ||
312 | { | ||
313 | struct bpf_insn *insn = buf; | ||
314 | unsigned int i; | ||
315 | |||
316 | for (i = 0; i < len / sizeof(*insn); i++) { | ||
317 | printf("% 4d: ", i); | ||
318 | print_bpf_insn(print_insn, NULL, insn + i, true); | ||
319 | |||
320 | if (opcodes) { | ||
321 | printf(" "); | ||
322 | print_hex(insn + i, 8, " "); | ||
323 | printf("\n"); | ||
324 | } | ||
325 | |||
326 | if (insn[i].code == (BPF_LD | BPF_IMM | BPF_DW)) | ||
327 | i++; | ||
328 | } | ||
329 | } | ||
330 | |||
300 | static int do_dump(int argc, char **argv) | 331 | static int do_dump(int argc, char **argv) |
301 | { | 332 | { |
302 | struct bpf_prog_info info = {}; | 333 | struct bpf_prog_info info = {}; |
303 | __u32 len = sizeof(info); | 334 | __u32 len = sizeof(info); |
304 | bool can_disasm = false; | ||
305 | unsigned int buf_size; | 335 | unsigned int buf_size; |
306 | char *filepath = NULL; | 336 | char *filepath = NULL; |
307 | bool opcodes = false; | 337 | bool opcodes = false; |
@@ -315,7 +345,6 @@ static int do_dump(int argc, char **argv) | |||
315 | if (is_prefix(*argv, "jited")) { | 345 | if (is_prefix(*argv, "jited")) { |
316 | member_len = &info.jited_prog_len; | 346 | member_len = &info.jited_prog_len; |
317 | member_ptr = &info.jited_prog_insns; | 347 | member_ptr = &info.jited_prog_insns; |
318 | can_disasm = true; | ||
319 | } else if (is_prefix(*argv, "xlated")) { | 348 | } else if (is_prefix(*argv, "xlated")) { |
320 | member_len = &info.xlated_prog_len; | 349 | member_len = &info.xlated_prog_len; |
321 | member_ptr = &info.xlated_prog_insns; | 350 | member_ptr = &info.xlated_prog_insns; |
@@ -346,10 +375,6 @@ static int do_dump(int argc, char **argv) | |||
346 | NEXT_ARG(); | 375 | NEXT_ARG(); |
347 | } | 376 | } |
348 | 377 | ||
349 | if (!filepath && !can_disasm) { | ||
350 | err("expected 'file' got %s\n", *argv); | ||
351 | return -1; | ||
352 | } | ||
353 | if (argc) { | 378 | if (argc) { |
354 | usage(); | 379 | usage(); |
355 | return -1; | 380 | return -1; |
@@ -409,7 +434,10 @@ static int do_dump(int argc, char **argv) | |||
409 | goto err_free; | 434 | goto err_free; |
410 | } | 435 | } |
411 | } else { | 436 | } else { |
412 | disasm_print_insn(buf, *member_len, opcodes); | 437 | if (member_len == &info.jited_prog_len) |
438 | disasm_print_insn(buf, *member_len, opcodes); | ||
439 | else | ||
440 | dump_xlated(buf, *member_len, opcodes); | ||
413 | } | 441 | } |
414 | 442 | ||
415 | free(buf); | 443 | free(buf); |
@@ -430,7 +458,7 @@ static int do_help(int argc, char **argv) | |||
430 | { | 458 | { |
431 | fprintf(stderr, | 459 | fprintf(stderr, |
432 | "Usage: %s %s show [PROG]\n" | 460 | "Usage: %s %s show [PROG]\n" |
433 | " %s %s dump xlated PROG file FILE\n" | 461 | " %s %s dump xlated PROG [file FILE] [opcodes]\n" |
434 | " %s %s dump jited PROG [file FILE] [opcodes]\n" | 462 | " %s %s dump jited PROG [file FILE] [opcodes]\n" |
435 | " %s %s pin PROG FILE\n" | 463 | " %s %s pin PROG FILE\n" |
436 | " %s %s help\n" | 464 | " %s %s help\n" |