aboutsummaryrefslogtreecommitdiffstats
path: root/tools/bpf/bpftool/prog.c
diff options
context:
space:
mode:
authorQuentin Monnet <quentin.monnet@netronome.com>2017-10-23 12:24:10 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-23 20:25:08 -0400
commitf05e2c32f715985f54265b1e237b5cce1b576c71 (patch)
treee2038a3c68b105bf6e58bb58d6c3d995a0bafe70 /tools/bpf/bpftool/prog.c
parent107f041212c1dfd3bf72b01c0d2013e98b6f32c2 (diff)
tools: bpftool: add JSON output for `bpftool prog dump xlated *` command
Add a new printing function to dump translated eBPF instructions as JSON. As for plain output, opcodes are printed only on request (when `opcodes` is provided on the command line). The disassembled output is generated by the same code that is used by the kernel verifier. Example output: $ bpftool --json --pretty prog dump xlated id 1 [{ "disasm": "(bf) r6 = r1" },{ "disasm": "(61) r7 = *(u32 *)(r6 +16)" },{ "disasm": "(95) exit" } ] $ bpftool --json --pretty prog dump xlated id 1 opcodes [{ "disasm": "(bf) r6 = r1", "opcodes": { "code": "0xbf", "src_reg": "0x1", "dst_reg": "0x6", "off": ["0x00","0x00" ], "imm": ["0x00","0x00","0x00","0x00" ] } },{ "disasm": "(61) r7 = *(u32 *)(r6 +16)", "opcodes": { "code": "0x61", "src_reg": "0x6", "dst_reg": "0x7", "off": ["0x10","0x00" ], "imm": ["0x00","0x00","0x00","0x00" ] } },{ "disasm": "(95) exit", "opcodes": { "code": "0x95", "src_reg": "0x0", "dst_reg": "0x0", "off": ["0x00","0x00" ], "imm": ["0x00","0x00","0x00","0x00" ] } } ] Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com> 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.c70
1 files changed, 68 insertions, 2 deletions
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index f373f2baef5a..43e49799a624 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -385,7 +385,7 @@ static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...)
385 va_end(args); 385 va_end(args);
386} 386}
387 387
388static void dump_xlated(void *buf, unsigned int len, bool opcodes) 388static void dump_xlated_plain(void *buf, unsigned int len, bool opcodes)
389{ 389{
390 struct bpf_insn *insn = buf; 390 struct bpf_insn *insn = buf;
391 bool double_insn = false; 391 bool double_insn = false;
@@ -414,6 +414,69 @@ static void dump_xlated(void *buf, unsigned int len, bool opcodes)
414 } 414 }
415} 415}
416 416
417static void print_insn_json(struct bpf_verifier_env *env, const char *fmt, ...)
418{
419 unsigned int l = strlen(fmt);
420 char chomped_fmt[l];
421 va_list args;
422
423 va_start(args, fmt);
424 if (l > 0) {
425 strncpy(chomped_fmt, fmt, l - 1);
426 chomped_fmt[l - 1] = '\0';
427 }
428 jsonw_vprintf_enquote(json_wtr, chomped_fmt, args);
429 va_end(args);
430}
431
432static void dump_xlated_json(void *buf, unsigned int len, bool opcodes)
433{
434 struct bpf_insn *insn = buf;
435 bool double_insn = false;
436 unsigned int i;
437
438 jsonw_start_array(json_wtr);
439 for (i = 0; i < len / sizeof(*insn); i++) {
440 if (double_insn) {
441 double_insn = false;
442 continue;
443 }
444 double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
445
446 jsonw_start_object(json_wtr);
447 jsonw_name(json_wtr, "disasm");
448 print_bpf_insn(print_insn_json, NULL, insn + i, true);
449
450 if (opcodes) {
451 jsonw_name(json_wtr, "opcodes");
452 jsonw_start_object(json_wtr);
453
454 jsonw_name(json_wtr, "code");
455 jsonw_printf(json_wtr, "\"0x%02hhx\"", insn[i].code);
456
457 jsonw_name(json_wtr, "src_reg");
458 jsonw_printf(json_wtr, "\"0x%hhx\"", insn[i].src_reg);
459
460 jsonw_name(json_wtr, "dst_reg");
461 jsonw_printf(json_wtr, "\"0x%hhx\"", insn[i].dst_reg);
462
463 jsonw_name(json_wtr, "off");
464 print_hex_data_json((uint8_t *)(&insn[i].off), 2);
465
466 jsonw_name(json_wtr, "imm");
467 if (double_insn && i < len - 1)
468 print_hex_data_json((uint8_t *)(&insn[i].imm),
469 12);
470 else
471 print_hex_data_json((uint8_t *)(&insn[i].imm),
472 4);
473 jsonw_end_object(json_wtr);
474 }
475 jsonw_end_object(json_wtr);
476 }
477 jsonw_end_array(json_wtr);
478}
479
417static int do_dump(int argc, char **argv) 480static int do_dump(int argc, char **argv)
418{ 481{
419 struct bpf_prog_info info = {}; 482 struct bpf_prog_info info = {};
@@ -523,7 +586,10 @@ static int do_dump(int argc, char **argv)
523 if (member_len == &info.jited_prog_len) 586 if (member_len == &info.jited_prog_len)
524 disasm_print_insn(buf, *member_len, opcodes); 587 disasm_print_insn(buf, *member_len, opcodes);
525 else 588 else
526 dump_xlated(buf, *member_len, opcodes); 589 if (json_output)
590 dump_xlated_json(buf, *member_len, opcodes);
591 else
592 dump_xlated_plain(buf, *member_len, opcodes);
527 } 593 }
528 594
529 free(buf); 595 free(buf);