Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Quentin Monnet and committed by
David S. Miller
107f0412 743cc665

+80 -6
+80 -6
tools/bpf/bpftool/jit_disasm.c
··· 10 10 * Licensed under the GNU General Public License, version 2.0 (GPLv2) 11 11 */ 12 12 13 + #include <stdarg.h> 13 14 #include <stdint.h> 14 15 #include <stdio.h> 15 16 #include <stdlib.h> ··· 21 20 #include <dis-asm.h> 22 21 #include <sys/types.h> 23 22 #include <sys/stat.h> 23 + 24 + #include "json_writer.h" 25 + #include "main.h" 24 26 25 27 static void get_exec_path(char *tpath, size_t size) 26 28 { ··· 41 37 tpath[len] = 0; 42 38 43 39 free(path); 40 + } 41 + 42 + static int oper_count; 43 + static int fprintf_json(void *out, const char *fmt, ...) 44 + { 45 + va_list ap; 46 + char *s; 47 + 48 + va_start(ap, fmt); 49 + if (!oper_count) { 50 + int i; 51 + 52 + s = va_arg(ap, char *); 53 + 54 + /* Strip trailing spaces */ 55 + i = strlen(s) - 1; 56 + while (s[i] == ' ') 57 + s[i--] = '\0'; 58 + 59 + jsonw_string_field(json_wtr, "operation", s); 60 + jsonw_name(json_wtr, "operands"); 61 + jsonw_start_array(json_wtr); 62 + oper_count++; 63 + } else if (!strcmp(fmt, ",")) { 64 + /* Skip */ 65 + } else { 66 + s = va_arg(ap, char *); 67 + jsonw_string(json_wtr, s); 68 + oper_count++; 69 + } 70 + va_end(ap); 71 + return 0; 44 72 } 45 73 46 74 void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes) ··· 93 57 assert(bfdf); 94 58 assert(bfd_check_format(bfdf, bfd_object)); 95 59 96 - init_disassemble_info(&info, stdout, (fprintf_ftype) fprintf); 60 + if (json_output) 61 + init_disassemble_info(&info, stdout, 62 + (fprintf_ftype) fprintf_json); 63 + else 64 + init_disassemble_info(&info, stdout, 65 + (fprintf_ftype) fprintf); 97 66 info.arch = bfd_get_arch(bfdf); 98 67 info.mach = bfd_get_mach(bfdf); 99 68 info.buffer = image; ··· 109 68 disassemble = disassembler(bfdf); 110 69 assert(disassemble); 111 70 71 + if (json_output) 72 + jsonw_start_array(json_wtr); 112 73 do { 113 - printf("%4x:\t", pc); 74 + if (json_output) { 75 + jsonw_start_object(json_wtr); 76 + oper_count = 0; 77 + jsonw_name(json_wtr, "pc"); 78 + jsonw_printf(json_wtr, "\"0x%x\"", pc); 79 + } else { 80 + printf("%4x:\t", pc); 81 + } 114 82 115 83 count = disassemble(pc, &info); 84 + if (json_output) { 85 + /* Operand array, was started in fprintf_json. Before 86 + * that, make sure we have a _null_ value if no operand 87 + * other than operation code was present. 88 + */ 89 + if (oper_count == 1) 90 + jsonw_null(json_wtr); 91 + jsonw_end_array(json_wtr); 92 + } 116 93 117 94 if (opcodes) { 118 - printf("\n\t"); 119 - for (i = 0; i < count; ++i) 120 - printf("%02x ", (uint8_t) image[pc + i]); 95 + if (json_output) { 96 + jsonw_name(json_wtr, "opcodes"); 97 + jsonw_start_array(json_wtr); 98 + for (i = 0; i < count; ++i) 99 + jsonw_printf(json_wtr, "\"0x%02hhx\"", 100 + (uint8_t)image[pc + i]); 101 + jsonw_end_array(json_wtr); 102 + } else { 103 + printf("\n\t"); 104 + for (i = 0; i < count; ++i) 105 + printf("%02x ", 106 + (uint8_t)image[pc + i]); 107 + } 121 108 } 122 - printf("\n"); 109 + if (json_output) 110 + jsonw_end_object(json_wtr); 111 + else 112 + printf("\n"); 123 113 124 114 pc += count; 125 115 } while (count > 0 && pc < len); 116 + if (json_output) 117 + jsonw_end_array(json_wtr); 126 118 127 119 bfd_close(bfdf); 128 120 }