summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuentin Monnet <quentin.monnet@netronome.com>2017-10-23 12:24:09 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-23 20:25:08 -0400
commit107f041212c1dfd3bf72b01c0d2013e98b6f32c2 (patch)
tree37d4592e19f1de25f2c42a77bd4e8a1cf571eba8
parent743cc665d5f62d2c75eceb59c461e653ad6ea58c (diff)
tools: bpftool: add JSON output for `bpftool prog dump jited *` command
Reuse the json_writer API introduced in an earlier commit to make bpftool able to generate JSON output on `bpftool prog show *` commands. A new printing function is created to be passed as an argument to the disassembler. Similarly to plain output, opcodes are printed on request. Outputs from sample programs have been successfully tested against a JSON validator. 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>
-rw-r--r--tools/bpf/bpftool/jit_disasm.c86
1 files changed, 80 insertions, 6 deletions
diff --git a/tools/bpf/bpftool/jit_disasm.c b/tools/bpf/bpftool/jit_disasm.c
index 70e480b59e9d..5937e134e408 100644
--- a/tools/bpf/bpftool/jit_disasm.c
+++ b/tools/bpf/bpftool/jit_disasm.c
@@ -10,6 +10,7 @@
10 * Licensed under the GNU General Public License, version 2.0 (GPLv2) 10 * Licensed under the GNU General Public License, version 2.0 (GPLv2)
11 */ 11 */
12 12
13#include <stdarg.h>
13#include <stdint.h> 14#include <stdint.h>
14#include <stdio.h> 15#include <stdio.h>
15#include <stdlib.h> 16#include <stdlib.h>
@@ -21,6 +22,9 @@
21#include <sys/types.h> 22#include <sys/types.h>
22#include <sys/stat.h> 23#include <sys/stat.h>
23 24
25#include "json_writer.h"
26#include "main.h"
27
24static void get_exec_path(char *tpath, size_t size) 28static void get_exec_path(char *tpath, size_t size)
25{ 29{
26 ssize_t len; 30 ssize_t len;
@@ -39,6 +43,38 @@ static void get_exec_path(char *tpath, size_t size)
39 free(path); 43 free(path);
40} 44}
41 45
46static int oper_count;
47static int fprintf_json(void *out, const char *fmt, ...)
48{
49 va_list ap;
50 char *s;
51
52 va_start(ap, fmt);
53 if (!oper_count) {
54 int i;
55
56 s = va_arg(ap, char *);
57
58 /* Strip trailing spaces */
59 i = strlen(s) - 1;
60 while (s[i] == ' ')
61 s[i--] = '\0';
62
63 jsonw_string_field(json_wtr, "operation", s);
64 jsonw_name(json_wtr, "operands");
65 jsonw_start_array(json_wtr);
66 oper_count++;
67 } else if (!strcmp(fmt, ",")) {
68 /* Skip */
69 } else {
70 s = va_arg(ap, char *);
71 jsonw_string(json_wtr, s);
72 oper_count++;
73 }
74 va_end(ap);
75 return 0;
76}
77
42void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes) 78void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes)
43{ 79{
44 disassembler_ftype disassemble; 80 disassembler_ftype disassemble;
@@ -57,7 +93,12 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes)
57 assert(bfdf); 93 assert(bfdf);
58 assert(bfd_check_format(bfdf, bfd_object)); 94 assert(bfd_check_format(bfdf, bfd_object));
59 95
60 init_disassemble_info(&info, stdout, (fprintf_ftype) fprintf); 96 if (json_output)
97 init_disassemble_info(&info, stdout,
98 (fprintf_ftype) fprintf_json);
99 else
100 init_disassemble_info(&info, stdout,
101 (fprintf_ftype) fprintf);
61 info.arch = bfd_get_arch(bfdf); 102 info.arch = bfd_get_arch(bfdf);
62 info.mach = bfd_get_mach(bfdf); 103 info.mach = bfd_get_mach(bfdf);
63 info.buffer = image; 104 info.buffer = image;
@@ -68,20 +109,53 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes)
68 disassemble = disassembler(bfdf); 109 disassemble = disassembler(bfdf);
69 assert(disassemble); 110 assert(disassemble);
70 111
112 if (json_output)
113 jsonw_start_array(json_wtr);
71 do { 114 do {
72 printf("%4x:\t", pc); 115 if (json_output) {
116 jsonw_start_object(json_wtr);
117 oper_count = 0;
118 jsonw_name(json_wtr, "pc");
119 jsonw_printf(json_wtr, "\"0x%x\"", pc);
120 } else {
121 printf("%4x:\t", pc);
122 }
73 123
74 count = disassemble(pc, &info); 124 count = disassemble(pc, &info);
125 if (json_output) {
126 /* Operand array, was started in fprintf_json. Before
127 * that, make sure we have a _null_ value if no operand
128 * other than operation code was present.
129 */
130 if (oper_count == 1)
131 jsonw_null(json_wtr);
132 jsonw_end_array(json_wtr);
133 }
75 134
76 if (opcodes) { 135 if (opcodes) {
77 printf("\n\t"); 136 if (json_output) {
78 for (i = 0; i < count; ++i) 137 jsonw_name(json_wtr, "opcodes");
79 printf("%02x ", (uint8_t) image[pc + i]); 138 jsonw_start_array(json_wtr);
139 for (i = 0; i < count; ++i)
140 jsonw_printf(json_wtr, "\"0x%02hhx\"",
141 (uint8_t)image[pc + i]);
142 jsonw_end_array(json_wtr);
143 } else {
144 printf("\n\t");
145 for (i = 0; i < count; ++i)
146 printf("%02x ",
147 (uint8_t)image[pc + i]);
148 }
80 } 149 }
81 printf("\n"); 150 if (json_output)
151 jsonw_end_object(json_wtr);
152 else
153 printf("\n");
82 154
83 pc += count; 155 pc += count;
84 } while (count > 0 && pc < len); 156 } while (count > 0 && pc < len);
157 if (json_output)
158 jsonw_end_array(json_wtr);
85 159
86 bfd_close(bfdf); 160 bfd_close(bfdf);
87} 161}