diff options
author | Yonghong Song <yhs@fb.com> | 2018-11-19 18:29:21 -0500 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2018-11-20 13:54:39 -0500 |
commit | 254471e57a86b8dc1a2cc19848e99f5d7c0558f4 (patch) | |
tree | 1892de2dc8c361322df68d459f0e63e59d901450 /tools/bpf/bpftool/prog.c | |
parent | 999d82cbc04416cc7f2b5cb6daab947c16f0fd3a (diff) |
tools/bpf: bpftool: add support for func types
This patch added support to print function signature
if btf func_info is available. Note that ksym
now uses function name instead of prog_name as
prog_name has a limit of 16 bytes including
ending '\0'.
The following is a sample output for selftests
test_btf with file test_btf_haskv.o for translated insns
and jited insns respectively.
$ bpftool prog dump xlated id 1
int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
0: (85) call pc+2#bpf_prog_2dcecc18072623fc_test_long_fname_1
1: (b7) r0 = 0
2: (95) exit
int test_long_fname_1(struct dummy_tracepoint_args * arg):
3: (85) call pc+1#bpf_prog_89d64e4abf0f0126_test_long_fname_2
4: (95) exit
int test_long_fname_2(struct dummy_tracepoint_args * arg):
5: (b7) r2 = 0
6: (63) *(u32 *)(r10 -4) = r2
7: (79) r1 = *(u64 *)(r1 +8)
...
22: (07) r1 += 1
23: (63) *(u32 *)(r0 +4) = r1
24: (95) exit
$ bpftool prog dump jited id 1
int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
bpf_prog_b07ccb89267cf242__dummy_tracepoint:
0: push %rbp
1: mov %rsp,%rbp
......
3c: add $0x28,%rbp
40: leaveq
41: retq
int test_long_fname_1(struct dummy_tracepoint_args * arg):
bpf_prog_2dcecc18072623fc_test_long_fname_1:
0: push %rbp
1: mov %rsp,%rbp
......
3a: add $0x28,%rbp
3e: leaveq
3f: retq
int test_long_fname_2(struct dummy_tracepoint_args * arg):
bpf_prog_89d64e4abf0f0126_test_long_fname_2:
0: push %rbp
1: mov %rsp,%rbp
......
80: add $0x28,%rbp
84: leaveq
85: retq
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/bpf/bpftool/prog.c')
-rw-r--r-- | tools/bpf/bpftool/prog.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index c176e1aa66fe..37b1daf19da6 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/err.h> | 47 | #include <linux/err.h> |
48 | 48 | ||
49 | #include <bpf.h> | 49 | #include <bpf.h> |
50 | #include <btf.h> | ||
50 | #include <libbpf.h> | 51 | #include <libbpf.h> |
51 | 52 | ||
52 | #include "cfg.h" | 53 | #include "cfg.h" |
@@ -451,14 +452,19 @@ static int do_dump(int argc, char **argv) | |||
451 | struct bpf_prog_info info = {}; | 452 | struct bpf_prog_info info = {}; |
452 | unsigned int *func_lens = NULL; | 453 | unsigned int *func_lens = NULL; |
453 | const char *disasm_opt = NULL; | 454 | const char *disasm_opt = NULL; |
455 | unsigned int finfo_rec_size; | ||
454 | unsigned int nr_func_ksyms; | 456 | unsigned int nr_func_ksyms; |
455 | unsigned int nr_func_lens; | 457 | unsigned int nr_func_lens; |
456 | struct dump_data dd = {}; | 458 | struct dump_data dd = {}; |
457 | __u32 len = sizeof(info); | 459 | __u32 len = sizeof(info); |
460 | struct btf *btf = NULL; | ||
461 | void *func_info = NULL; | ||
462 | unsigned int finfo_cnt; | ||
458 | unsigned int buf_size; | 463 | unsigned int buf_size; |
459 | char *filepath = NULL; | 464 | char *filepath = NULL; |
460 | bool opcodes = false; | 465 | bool opcodes = false; |
461 | bool visual = false; | 466 | bool visual = false; |
467 | char func_sig[1024]; | ||
462 | unsigned char *buf; | 468 | unsigned char *buf; |
463 | __u32 *member_len; | 469 | __u32 *member_len; |
464 | __u64 *member_ptr; | 470 | __u64 *member_ptr; |
@@ -551,6 +557,17 @@ static int do_dump(int argc, char **argv) | |||
551 | } | 557 | } |
552 | } | 558 | } |
553 | 559 | ||
560 | finfo_cnt = info.func_info_cnt; | ||
561 | finfo_rec_size = info.func_info_rec_size; | ||
562 | if (finfo_cnt && finfo_rec_size) { | ||
563 | func_info = malloc(finfo_cnt * finfo_rec_size); | ||
564 | if (!func_info) { | ||
565 | p_err("mem alloc failed"); | ||
566 | close(fd); | ||
567 | goto err_free; | ||
568 | } | ||
569 | } | ||
570 | |||
554 | memset(&info, 0, sizeof(info)); | 571 | memset(&info, 0, sizeof(info)); |
555 | 572 | ||
556 | *member_ptr = ptr_to_u64(buf); | 573 | *member_ptr = ptr_to_u64(buf); |
@@ -559,6 +576,9 @@ static int do_dump(int argc, char **argv) | |||
559 | info.nr_jited_ksyms = nr_func_ksyms; | 576 | info.nr_jited_ksyms = nr_func_ksyms; |
560 | info.jited_func_lens = ptr_to_u64(func_lens); | 577 | info.jited_func_lens = ptr_to_u64(func_lens); |
561 | info.nr_jited_func_lens = nr_func_lens; | 578 | info.nr_jited_func_lens = nr_func_lens; |
579 | info.func_info_cnt = finfo_cnt; | ||
580 | info.func_info_rec_size = finfo_rec_size; | ||
581 | info.func_info = ptr_to_u64(func_info); | ||
562 | 582 | ||
563 | err = bpf_obj_get_info_by_fd(fd, &info, &len); | 583 | err = bpf_obj_get_info_by_fd(fd, &info, &len); |
564 | close(fd); | 584 | close(fd); |
@@ -582,6 +602,18 @@ static int do_dump(int argc, char **argv) | |||
582 | goto err_free; | 602 | goto err_free; |
583 | } | 603 | } |
584 | 604 | ||
605 | if (info.func_info_cnt != finfo_cnt) { | ||
606 | p_err("incorrect func_info_cnt %d vs. expected %d", | ||
607 | info.func_info_cnt, finfo_cnt); | ||
608 | goto err_free; | ||
609 | } | ||
610 | |||
611 | if (info.func_info_rec_size != finfo_rec_size) { | ||
612 | p_err("incorrect func_info_rec_size %d vs. expected %d", | ||
613 | info.func_info_rec_size, finfo_rec_size); | ||
614 | goto err_free; | ||
615 | } | ||
616 | |||
585 | if ((member_len == &info.jited_prog_len && | 617 | if ((member_len == &info.jited_prog_len && |
586 | info.jited_prog_insns == 0) || | 618 | info.jited_prog_insns == 0) || |
587 | (member_len == &info.xlated_prog_len && | 619 | (member_len == &info.xlated_prog_len && |
@@ -590,6 +622,11 @@ static int do_dump(int argc, char **argv) | |||
590 | goto err_free; | 622 | goto err_free; |
591 | } | 623 | } |
592 | 624 | ||
625 | if (info.btf_id && btf_get_from_id(info.btf_id, &btf)) { | ||
626 | p_err("failed to get btf"); | ||
627 | goto err_free; | ||
628 | } | ||
629 | |||
593 | if (filepath) { | 630 | if (filepath) { |
594 | fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600); | 631 | fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600); |
595 | if (fd < 0) { | 632 | if (fd < 0) { |
@@ -622,6 +659,7 @@ static int do_dump(int argc, char **argv) | |||
622 | 659 | ||
623 | if (info.nr_jited_func_lens && info.jited_func_lens) { | 660 | if (info.nr_jited_func_lens && info.jited_func_lens) { |
624 | struct kernel_sym *sym = NULL; | 661 | struct kernel_sym *sym = NULL; |
662 | struct bpf_func_info *record; | ||
625 | char sym_name[SYM_MAX_NAME]; | 663 | char sym_name[SYM_MAX_NAME]; |
626 | unsigned char *img = buf; | 664 | unsigned char *img = buf; |
627 | __u64 *ksyms = NULL; | 665 | __u64 *ksyms = NULL; |
@@ -648,12 +686,25 @@ static int do_dump(int argc, char **argv) | |||
648 | strcpy(sym_name, "unknown"); | 686 | strcpy(sym_name, "unknown"); |
649 | } | 687 | } |
650 | 688 | ||
689 | if (func_info) { | ||
690 | record = func_info + i * finfo_rec_size; | ||
691 | btf_dumper_type_only(btf, record->type_id, | ||
692 | func_sig, | ||
693 | sizeof(func_sig)); | ||
694 | } | ||
695 | |||
651 | if (json_output) { | 696 | if (json_output) { |
652 | jsonw_start_object(json_wtr); | 697 | jsonw_start_object(json_wtr); |
698 | if (func_info && func_sig[0] != '\0') { | ||
699 | jsonw_name(json_wtr, "proto"); | ||
700 | jsonw_string(json_wtr, func_sig); | ||
701 | } | ||
653 | jsonw_name(json_wtr, "name"); | 702 | jsonw_name(json_wtr, "name"); |
654 | jsonw_string(json_wtr, sym_name); | 703 | jsonw_string(json_wtr, sym_name); |
655 | jsonw_name(json_wtr, "insns"); | 704 | jsonw_name(json_wtr, "insns"); |
656 | } else { | 705 | } else { |
706 | if (func_info && func_sig[0] != '\0') | ||
707 | printf("%s:\n", func_sig); | ||
657 | printf("%s:\n", sym_name); | 708 | printf("%s:\n", sym_name); |
658 | } | 709 | } |
659 | 710 | ||
@@ -682,6 +733,9 @@ static int do_dump(int argc, char **argv) | |||
682 | kernel_syms_load(&dd); | 733 | kernel_syms_load(&dd); |
683 | dd.nr_jited_ksyms = info.nr_jited_ksyms; | 734 | dd.nr_jited_ksyms = info.nr_jited_ksyms; |
684 | dd.jited_ksyms = (__u64 *) info.jited_ksyms; | 735 | dd.jited_ksyms = (__u64 *) info.jited_ksyms; |
736 | dd.btf = btf; | ||
737 | dd.func_info = func_info; | ||
738 | dd.finfo_rec_size = finfo_rec_size; | ||
685 | 739 | ||
686 | if (json_output) | 740 | if (json_output) |
687 | dump_xlated_json(&dd, buf, *member_len, opcodes); | 741 | dump_xlated_json(&dd, buf, *member_len, opcodes); |
@@ -693,12 +747,14 @@ static int do_dump(int argc, char **argv) | |||
693 | free(buf); | 747 | free(buf); |
694 | free(func_ksyms); | 748 | free(func_ksyms); |
695 | free(func_lens); | 749 | free(func_lens); |
750 | free(func_info); | ||
696 | return 0; | 751 | return 0; |
697 | 752 | ||
698 | err_free: | 753 | err_free: |
699 | free(buf); | 754 | free(buf); |
700 | free(func_ksyms); | 755 | free(func_ksyms); |
701 | free(func_lens); | 756 | free(func_lens); |
757 | free(func_info); | ||
702 | return -1; | 758 | return -1; |
703 | } | 759 | } |
704 | 760 | ||