summaryrefslogtreecommitdiffstats
path: root/tools/bpf
diff options
context:
space:
mode:
authorSandipan Das <sandipan@linux.vnet.ibm.com>2018-05-24 02:56:54 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2018-05-24 03:20:50 -0400
commitf7f62c7134288a704f90b137097e1ee689ff25ab (patch)
tree368c31f0f2cd07cab7ff8abd445b8dc84aa761ec /tools/bpf
parentbd980d43b977c0b6582be906da23b08e0ae1b3dc (diff)
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: Sandipan Das <sandipan@linux.vnet.ibm.com> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'tools/bpf')
-rw-r--r--tools/bpf/bpftool/prog.c73
-rw-r--r--tools/bpf/bpftool/xlated_dumper.c4
-rw-r--r--tools/bpf/bpftool/xlated_dumper.h1
3 files changed, 75 insertions, 3 deletions
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index e05ab58d39e2..39b88e760367 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -422,7 +422,9 @@ static int do_dump(int argc, char **argv)
422{ 422{
423 unsigned long *func_ksyms = NULL; 423 unsigned long *func_ksyms = NULL;
424 struct bpf_prog_info info = {}; 424 struct bpf_prog_info info = {};
425 unsigned int *func_lens = NULL;
425 unsigned int nr_func_ksyms; 426 unsigned int nr_func_ksyms;
427 unsigned int nr_func_lens;
426 struct dump_data dd = {}; 428 struct dump_data dd = {};
427 __u32 len = sizeof(info); 429 __u32 len = sizeof(info);
428 unsigned int buf_size; 430 unsigned int buf_size;
@@ -508,12 +510,24 @@ static int do_dump(int argc, char **argv)
508 } 510 }
509 } 511 }
510 512
513 nr_func_lens = info.nr_jited_func_lens;
514 if (nr_func_lens) {
515 func_lens = malloc(nr_func_lens * sizeof(__u32));
516 if (!func_lens) {
517 p_err("mem alloc failed");
518 close(fd);
519 goto err_free;
520 }
521 }
522
511 memset(&info, 0, sizeof(info)); 523 memset(&info, 0, sizeof(info));
512 524
513 *member_ptr = ptr_to_u64(buf); 525 *member_ptr = ptr_to_u64(buf);
514 *member_len = buf_size; 526 *member_len = buf_size;
515 info.jited_ksyms = ptr_to_u64(func_ksyms); 527 info.jited_ksyms = ptr_to_u64(func_ksyms);
516 info.nr_jited_ksyms = nr_func_ksyms; 528 info.nr_jited_ksyms = nr_func_ksyms;
529 info.jited_func_lens = ptr_to_u64(func_lens);
530 info.nr_jited_func_lens = nr_func_lens;
517 531
518 err = bpf_obj_get_info_by_fd(fd, &info, &len); 532 err = bpf_obj_get_info_by_fd(fd, &info, &len);
519 close(fd); 533 close(fd);
@@ -532,6 +546,11 @@ static int do_dump(int argc, char **argv)
532 goto err_free; 546 goto err_free;
533 } 547 }
534 548
549 if (info.nr_jited_func_lens > nr_func_lens) {
550 p_err("too many values returned");
551 goto err_free;
552 }
553
535 if ((member_len == &info.jited_prog_len && 554 if ((member_len == &info.jited_prog_len &&
536 info.jited_prog_insns == 0) || 555 info.jited_prog_insns == 0) ||
537 (member_len == &info.xlated_prog_len && 556 (member_len == &info.xlated_prog_len &&
@@ -569,7 +588,57 @@ static int do_dump(int argc, char **argv)
569 goto err_free; 588 goto err_free;
570 } 589 }
571 590
572 disasm_print_insn(buf, *member_len, opcodes, name); 591 if (info.nr_jited_func_lens && info.jited_func_lens) {
592 struct kernel_sym *sym = NULL;
593 char sym_name[SYM_MAX_NAME];
594 unsigned char *img = buf;
595 __u64 *ksyms = NULL;
596 __u32 *lens;
597 __u32 i;
598
599 if (info.nr_jited_ksyms) {
600 kernel_syms_load(&dd);
601 ksyms = (__u64 *) info.jited_ksyms;
602 }
603
604 if (json_output)
605 jsonw_start_array(json_wtr);
606
607 lens = (__u32 *) info.jited_func_lens;
608 for (i = 0; i < info.nr_jited_func_lens; i++) {
609 if (ksyms) {
610 sym = kernel_syms_search(&dd, ksyms[i]);
611 if (sym)
612 sprintf(sym_name, "%s", sym->name);
613 else
614 sprintf(sym_name, "0x%016llx", ksyms[i]);
615 } else {
616 strcpy(sym_name, "unknown");
617 }
618
619 if (json_output) {
620 jsonw_start_object(json_wtr);
621 jsonw_name(json_wtr, "name");
622 jsonw_string(json_wtr, sym_name);
623 jsonw_name(json_wtr, "insns");
624 } else {
625 printf("%s:\n", sym_name);
626 }
627
628 disasm_print_insn(img, lens[i], opcodes, name);
629 img += lens[i];
630
631 if (json_output)
632 jsonw_end_object(json_wtr);
633 else
634 printf("\n");
635 }
636
637 if (json_output)
638 jsonw_end_array(json_wtr);
639 } else {
640 disasm_print_insn(buf, *member_len, opcodes, name);
641 }
573 } else if (visual) { 642 } else if (visual) {
574 if (json_output) 643 if (json_output)
575 jsonw_null(json_wtr); 644 jsonw_null(json_wtr);
@@ -589,11 +658,13 @@ static int do_dump(int argc, char **argv)
589 658
590 free(buf); 659 free(buf);
591 free(func_ksyms); 660 free(func_ksyms);
661 free(func_lens);
592 return 0; 662 return 0;
593 663
594err_free: 664err_free:
595 free(buf); 665 free(buf);
596 free(func_ksyms); 666 free(func_ksyms);
667 free(func_lens);
597 return -1; 668 return -1;
598} 669}
599 670
diff --git a/tools/bpf/bpftool/xlated_dumper.c b/tools/bpf/bpftool/xlated_dumper.c
index efdc8fecf2bb..b97f1da60dd1 100644
--- a/tools/bpf/bpftool/xlated_dumper.c
+++ b/tools/bpf/bpftool/xlated_dumper.c
@@ -102,8 +102,8 @@ void kernel_syms_destroy(struct dump_data *dd)
102 free(dd->sym_mapping); 102 free(dd->sym_mapping);
103} 103}
104 104
105static struct kernel_sym *kernel_syms_search(struct dump_data *dd, 105struct kernel_sym *kernel_syms_search(struct dump_data *dd,
106 unsigned long key) 106 unsigned long key)
107{ 107{
108 struct kernel_sym sym = { 108 struct kernel_sym sym = {
109 .address = key, 109 .address = key,
diff --git a/tools/bpf/bpftool/xlated_dumper.h b/tools/bpf/bpftool/xlated_dumper.h
index eafbb49c8d0b..33d86e2b369b 100644
--- a/tools/bpf/bpftool/xlated_dumper.h
+++ b/tools/bpf/bpftool/xlated_dumper.h
@@ -56,6 +56,7 @@ struct dump_data {
56 56
57void kernel_syms_load(struct dump_data *dd); 57void kernel_syms_load(struct dump_data *dd);
58void kernel_syms_destroy(struct dump_data *dd); 58void kernel_syms_destroy(struct dump_data *dd);
59struct kernel_sym *kernel_syms_search(struct dump_data *dd, unsigned long key);
59void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len, 60void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,
60 bool opcodes); 61 bool opcodes);
61void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len, 62void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len,