Commit f7f62c71 authored by Sandipan Das's avatar Sandipan Das Committed by Daniel Borkmann

tools: bpftool: add delimiters to multi-function JITed dumps

This splits up the contiguous JITed dump obtained via the bpf
system call into more relatable chunks for each function in
the program. If the kernel symbols corresponding to these are
known, they are printed in the header for each JIT image dump
otherwise the masked start address is printed.

Before applying this patch:

  # bpftool prog dump jited id 1

     0:	push   %rbp
     1:	mov    %rsp,%rbp
  ...
    70:	leaveq
    71:	retq
    72:	push   %rbp
    73:	mov    %rsp,%rbp
  ...
    dd:	leaveq
    de:	retq

  # bpftool -p prog dump jited id 1

  [{
          "pc": "0x0",
          "operation": "push",
          "operands": ["%rbp"
          ]
      },{
  ...
      },{
          "pc": "0x71",
          "operation": "retq",
          "operands": [null
          ]
      },{
          "pc": "0x72",
          "operation": "push",
          "operands": ["%rbp"
          ]
      },{
  ...
      },{
          "pc": "0xde",
          "operation": "retq",
          "operands": [null
          ]
      }
  ]

After applying this patch:

  # echo 0 > /proc/sys/net/core/bpf_jit_kallsyms
  # bpftool prog dump jited id 1

  0xffffffffc02c7000:
     0:	push   %rbp
     1:	mov    %rsp,%rbp
  ...
    70:	leaveq
    71:	retq

  0xffffffffc02cf000:
     0:	push   %rbp
     1:	mov    %rsp,%rbp
  ...
    6b:	leaveq
    6c:	retq

  # bpftool -p prog dump jited id 1

  [{
          "name": "0xffffffffc02c7000",
          "insns": [{
                  "pc": "0x0",
                  "operation": "push",
                  "operands": ["%rbp"
                  ]
              },{
  ...
              },{
                  "pc": "0x71",
                  "operation": "retq",
                  "operands": [null
                  ]
              }
          ]
      },{
          "name": "0xffffffffc02cf000",
          "insns": [{
                  "pc": "0x0",
                  "operation": "push",
                  "operands": ["%rbp"
                  ]
              },{
  ...
              },{
                  "pc": "0x6c",
                  "operation": "retq",
                  "operands": [null
                  ]
              }
          ]
      }
  ]

  # echo 1 > /proc/sys/net/core/bpf_jit_kallsyms
  # bpftool prog dump jited id 1

  bpf_prog_b811aab41a39ad3d_foo:
     0:	push   %rbp
     1:	mov    %rsp,%rbp
  ...
    70:	leaveq
    71:	retq

  bpf_prog_cf418ac8b67bebd9_F:
     0:	push   %rbp
     1:	mov    %rsp,%rbp
  ...
    6b:	leaveq
    6c:	retq

  # bpftool -p prog dump jited id 1

  [{
          "name": "bpf_prog_b811aab41a39ad3d_foo",
          "insns": [{
                  "pc": "0x0",
                  "operation": "push",
                  "operands": ["%rbp"
                  ]
              },{
  ...
              },{
                  "pc": "0x71",
                  "operation": "retq",
                  "operands": [null
                  ]
              }
          ]
      },{
          "name": "bpf_prog_cf418ac8b67bebd9_F",
          "insns": [{
                  "pc": "0x0",
                  "operation": "push",
                  "operands": ["%rbp"
                  ]
              },{
  ...
              },{
                  "pc": "0x6c",
                  "operation": "retq",
                  "operands": [null
                  ]
              }
          ]
      }
  ]
Signed-off-by: default avatarSandipan Das <sandipan@linux.vnet.ibm.com>
Reviewed-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent bd980d43
...@@ -422,7 +422,9 @@ static int do_dump(int argc, char **argv) ...@@ -422,7 +422,9 @@ static int do_dump(int argc, char **argv)
{ {
unsigned long *func_ksyms = NULL; unsigned long *func_ksyms = NULL;
struct bpf_prog_info info = {}; struct bpf_prog_info info = {};
unsigned int *func_lens = NULL;
unsigned int nr_func_ksyms; unsigned int nr_func_ksyms;
unsigned int nr_func_lens;
struct dump_data dd = {}; struct dump_data dd = {};
__u32 len = sizeof(info); __u32 len = sizeof(info);
unsigned int buf_size; unsigned int buf_size;
...@@ -508,12 +510,24 @@ static int do_dump(int argc, char **argv) ...@@ -508,12 +510,24 @@ static int do_dump(int argc, char **argv)
} }
} }
nr_func_lens = info.nr_jited_func_lens;
if (nr_func_lens) {
func_lens = malloc(nr_func_lens * sizeof(__u32));
if (!func_lens) {
p_err("mem alloc failed");
close(fd);
goto err_free;
}
}
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
*member_ptr = ptr_to_u64(buf); *member_ptr = ptr_to_u64(buf);
*member_len = buf_size; *member_len = buf_size;
info.jited_ksyms = ptr_to_u64(func_ksyms); info.jited_ksyms = ptr_to_u64(func_ksyms);
info.nr_jited_ksyms = nr_func_ksyms; info.nr_jited_ksyms = nr_func_ksyms;
info.jited_func_lens = ptr_to_u64(func_lens);
info.nr_jited_func_lens = nr_func_lens;
err = bpf_obj_get_info_by_fd(fd, &info, &len); err = bpf_obj_get_info_by_fd(fd, &info, &len);
close(fd); close(fd);
...@@ -532,6 +546,11 @@ static int do_dump(int argc, char **argv) ...@@ -532,6 +546,11 @@ static int do_dump(int argc, char **argv)
goto err_free; goto err_free;
} }
if (info.nr_jited_func_lens > nr_func_lens) {
p_err("too many values returned");
goto err_free;
}
if ((member_len == &info.jited_prog_len && if ((member_len == &info.jited_prog_len &&
info.jited_prog_insns == 0) || info.jited_prog_insns == 0) ||
(member_len == &info.xlated_prog_len && (member_len == &info.xlated_prog_len &&
...@@ -569,7 +588,57 @@ static int do_dump(int argc, char **argv) ...@@ -569,7 +588,57 @@ static int do_dump(int argc, char **argv)
goto err_free; goto err_free;
} }
if (info.nr_jited_func_lens && info.jited_func_lens) {
struct kernel_sym *sym = NULL;
char sym_name[SYM_MAX_NAME];
unsigned char *img = buf;
__u64 *ksyms = NULL;
__u32 *lens;
__u32 i;
if (info.nr_jited_ksyms) {
kernel_syms_load(&dd);
ksyms = (__u64 *) info.jited_ksyms;
}
if (json_output)
jsonw_start_array(json_wtr);
lens = (__u32 *) info.jited_func_lens;
for (i = 0; i < info.nr_jited_func_lens; i++) {
if (ksyms) {
sym = kernel_syms_search(&dd, ksyms[i]);
if (sym)
sprintf(sym_name, "%s", sym->name);
else
sprintf(sym_name, "0x%016llx", ksyms[i]);
} else {
strcpy(sym_name, "unknown");
}
if (json_output) {
jsonw_start_object(json_wtr);
jsonw_name(json_wtr, "name");
jsonw_string(json_wtr, sym_name);
jsonw_name(json_wtr, "insns");
} else {
printf("%s:\n", sym_name);
}
disasm_print_insn(img, lens[i], opcodes, name);
img += lens[i];
if (json_output)
jsonw_end_object(json_wtr);
else
printf("\n");
}
if (json_output)
jsonw_end_array(json_wtr);
} else {
disasm_print_insn(buf, *member_len, opcodes, name); disasm_print_insn(buf, *member_len, opcodes, name);
}
} else if (visual) { } else if (visual) {
if (json_output) if (json_output)
jsonw_null(json_wtr); jsonw_null(json_wtr);
...@@ -589,11 +658,13 @@ static int do_dump(int argc, char **argv) ...@@ -589,11 +658,13 @@ static int do_dump(int argc, char **argv)
free(buf); free(buf);
free(func_ksyms); free(func_ksyms);
free(func_lens);
return 0; return 0;
err_free: err_free:
free(buf); free(buf);
free(func_ksyms); free(func_ksyms);
free(func_lens);
return -1; return -1;
} }
......
...@@ -102,7 +102,7 @@ void kernel_syms_destroy(struct dump_data *dd) ...@@ -102,7 +102,7 @@ void kernel_syms_destroy(struct dump_data *dd)
free(dd->sym_mapping); free(dd->sym_mapping);
} }
static struct kernel_sym *kernel_syms_search(struct dump_data *dd, struct kernel_sym *kernel_syms_search(struct dump_data *dd,
unsigned long key) unsigned long key)
{ {
struct kernel_sym sym = { struct kernel_sym sym = {
......
...@@ -56,6 +56,7 @@ struct dump_data { ...@@ -56,6 +56,7 @@ struct dump_data {
void kernel_syms_load(struct dump_data *dd); void kernel_syms_load(struct dump_data *dd);
void kernel_syms_destroy(struct dump_data *dd); void kernel_syms_destroy(struct dump_data *dd);
struct kernel_sym *kernel_syms_search(struct dump_data *dd, unsigned long key);
void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len, void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,
bool opcodes); bool opcodes);
void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len, void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment