From 393de512e719a5fbd6712fc392a571ab287eb8ab Mon Sep 17 00:00:00 2001 From: Andrey Ignatov Date: Tue, 17 Apr 2018 10:28:44 -0700 Subject: bpftool: Support new prog types and attach types Add recently added prog types to `bpftool prog` and attach types to `bpftool cgroup`. Update bpftool documentation and bash completion appropriately. Signed-off-by: Andrey Ignatov Acked-by: Jakub Kicinski Signed-off-by: Daniel Borkmann --- tools/bpf/bpftool/prog.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools/bpf/bpftool/prog.c') diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index f7a810897eac..548adb9b7317 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -68,6 +68,9 @@ static const char * const prog_type_name[] = { [BPF_PROG_TYPE_SOCK_OPS] = "sock_ops", [BPF_PROG_TYPE_SK_SKB] = "sk_skb", [BPF_PROG_TYPE_CGROUP_DEVICE] = "cgroup_device", + [BPF_PROG_TYPE_SK_MSG] = "sk_msg", + [BPF_PROG_TYPE_RAW_TRACEPOINT] = "raw_tracepoint", + [BPF_PROG_TYPE_CGROUP_SOCK_ADDR] = "cgroup_sock_addr", }; static void print_boot_time(__u64 nsecs, char *buf, unsigned int size) -- cgit v1.2.3 From 9b984a20ca84337af81cdab92d1e8ae37007894a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 26 Apr 2018 10:18:01 +0200 Subject: tools, bpftool: Display license GPL compatible in prog show/list Display the license "gpl" string in bpftool prog command, like: # bpftool prog list 5: tracepoint name func tag 57cd311f2e27366b gpl loaded_at Apr 26/09:37 uid 0 xlated 16B not jited memlock 4096B # bpftool --json --pretty prog show [{ "id": 5, "type": "tracepoint", "name": "func", "tag": "57cd311f2e27366b", "gpl_compatible": true, "loaded_at": "Apr 26/09:37", "uid": 0, "bytes_xlated": 16, "jited": false, "bytes_memlock": 4096 } ] Signed-off-by: Jiri Olsa Signed-off-by: Daniel Borkmann --- tools/bpf/bpftool/prog.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools/bpf/bpftool/prog.c') diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 548adb9b7317..e71a0a11afde 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -235,6 +235,8 @@ static void print_prog_json(struct bpf_prog_info *info, int fd) info->tag[0], info->tag[1], info->tag[2], info->tag[3], info->tag[4], info->tag[5], info->tag[6], info->tag[7]); + jsonw_bool_field(json_wtr, "gpl_compatible", info->gpl_compatible); + print_dev_json(info->ifindex, info->netns_dev, info->netns_ino); if (info->load_time) { @@ -295,6 +297,7 @@ static void print_prog_plain(struct bpf_prog_info *info, int fd) printf("tag "); fprint_hex(stdout, info->tag, BPF_TAG_SIZE, ""); print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino); + printf("%s", info->gpl_compatible ? " gpl" : ""); printf("\n"); if (info->load_time) { -- cgit v1.2.3 From a3fe1f6f2adaa01c620793666d489a584211ecba Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Tue, 1 May 2018 21:18:38 +0100 Subject: tools: bpftool: change time format for program 'loaded at:' information To make eBPF program load time easier to parse from "bpftool prog" output for machines, change the time format used by the program. The format now differs for plain and JSON version: - Plain version uses a string formatted according to ISO 8601. - JSON uses the number of seconds since the Epoch, wich is less friendly for humans but even easier to process. Example output: # ./bpftool prog 41298: xdp tag a04f5eef06a7f555 dev foo loaded_at 2018-04-18T17:19:47+0100 uid 0 xlated 16B not jited memlock 4096B # ./bpftool prog -p [{ "id": 41298, "type": "xdp", "tag": "a04f5eef06a7f555", "gpl_compatible": false, "dev": { "ifindex": 14, "ns_dev": 3, "ns_inode": 4026531993, "ifname": "foo" }, "loaded_at": 1524068387, "uid": 0, "bytes_xlated": 16, "jited": false, "bytes_memlock": 4096 } ] Previously, "Apr 18/17:19" would be used at both places. Suggested-by: Alexei Starovoitov Signed-off-by: Quentin Monnet Acked-by: Jakub Kicinski Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/prog.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'tools/bpf/bpftool/prog.c') diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index e71a0a11afde..9bdfdf2d3fbe 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -96,7 +96,10 @@ static void print_boot_time(__u64 nsecs, char *buf, unsigned int size) return; } - strftime(buf, size, "%b %d/%H:%M", &load_tm); + if (json_output) + strftime(buf, size, "%s", &load_tm); + else + strftime(buf, size, "%FT%T%z", &load_tm); } static int prog_fd_by_tag(unsigned char *tag) @@ -245,7 +248,8 @@ static void print_prog_json(struct bpf_prog_info *info, int fd) print_boot_time(info->load_time, buf, sizeof(buf)); /* Piggy back on load_time, since 0 uid is a valid one */ - jsonw_string_field(json_wtr, "loaded_at", buf); + jsonw_name(json_wtr, "loaded_at"); + jsonw_printf(json_wtr, "%s", buf); jsonw_uint_field(json_wtr, "uid", info->created_by_uid); } -- cgit v1.2.3 From f84192ee00b7d8b3c38545d3a61d4191f80cc81a Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Thu, 24 May 2018 12:26:50 +0530 Subject: tools: bpftool: resolve calls without using imm field Currently, we resolve the callee's address for a JITed function call by using the imm field of the call instruction as an offset from __bpf_call_base. If bpf_jit_kallsyms is enabled, we further use this address to get the callee's kernel symbol's name. For some architectures, such as powerpc64, the imm field is not large enough to hold this offset. So, instead of assigning this offset to the imm field, the verifier now assigns the subprog id. Also, a list of kernel symbol addresses for all the JITed functions is provided in the program info. We now use the imm field as an index for this list to lookup a callee's symbol's address and resolve its name. Suggested-by: Daniel Borkmann Signed-off-by: Sandipan Das Reviewed-by: Jakub Kicinski Signed-off-by: Daniel Borkmann --- tools/bpf/bpftool/prog.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'tools/bpf/bpftool/prog.c') diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 9bdfdf2d3fbe..e05ab58d39e2 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -420,7 +420,9 @@ static int do_show(int argc, char **argv) static int do_dump(int argc, char **argv) { + unsigned long *func_ksyms = NULL; struct bpf_prog_info info = {}; + unsigned int nr_func_ksyms; struct dump_data dd = {}; __u32 len = sizeof(info); unsigned int buf_size; @@ -496,10 +498,22 @@ static int do_dump(int argc, char **argv) return -1; } + nr_func_ksyms = info.nr_jited_ksyms; + if (nr_func_ksyms) { + func_ksyms = malloc(nr_func_ksyms * sizeof(__u64)); + if (!func_ksyms) { + p_err("mem alloc failed"); + close(fd); + goto err_free; + } + } + memset(&info, 0, sizeof(info)); *member_ptr = ptr_to_u64(buf); *member_len = buf_size; + info.jited_ksyms = ptr_to_u64(func_ksyms); + info.nr_jited_ksyms = nr_func_ksyms; err = bpf_obj_get_info_by_fd(fd, &info, &len); close(fd); @@ -513,6 +527,11 @@ static int do_dump(int argc, char **argv) goto err_free; } + if (info.nr_jited_ksyms > nr_func_ksyms) { + p_err("too many addresses returned"); + goto err_free; + } + if ((member_len == &info.jited_prog_len && info.jited_prog_insns == 0) || (member_len == &info.xlated_prog_len && @@ -558,6 +577,9 @@ static int do_dump(int argc, char **argv) dump_xlated_cfg(buf, *member_len); } else { kernel_syms_load(&dd); + dd.nr_jited_ksyms = info.nr_jited_ksyms; + dd.jited_ksyms = (__u64 *) info.jited_ksyms; + if (json_output) dump_xlated_json(&dd, buf, *member_len, opcodes); else @@ -566,10 +588,12 @@ static int do_dump(int argc, char **argv) } free(buf); + free(func_ksyms); return 0; err_free: free(buf); + free(func_ksyms); return -1; } -- cgit v1.2.3 From f7f62c7134288a704f90b137097e1ee689ff25ab Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Thu, 24 May 2018 12:26:54 +0530 Subject: 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 Reviewed-by: Jakub Kicinski Signed-off-by: Daniel Borkmann --- tools/bpf/bpftool/prog.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) (limited to 'tools/bpf/bpftool/prog.c') 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) { unsigned long *func_ksyms = NULL; struct bpf_prog_info info = {}; + unsigned int *func_lens = NULL; unsigned int nr_func_ksyms; + unsigned int nr_func_lens; struct dump_data dd = {}; __u32 len = sizeof(info); unsigned int buf_size; @@ -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)); *member_ptr = ptr_to_u64(buf); *member_len = buf_size; info.jited_ksyms = ptr_to_u64(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); close(fd); @@ -532,6 +546,11 @@ static int do_dump(int argc, char **argv) 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 && info.jited_prog_insns == 0) || (member_len == &info.xlated_prog_len && @@ -569,7 +588,57 @@ static int do_dump(int argc, char **argv) goto err_free; } - disasm_print_insn(buf, *member_len, opcodes, name); + 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); + } } else if (visual) { if (json_output) jsonw_null(json_wtr); @@ -589,11 +658,13 @@ static int do_dump(int argc, char **argv) free(buf); free(func_ksyms); + free(func_lens); return 0; err_free: free(buf); free(func_ksyms); + free(func_lens); return -1; } -- cgit v1.2.3 From 6bdd533cee9aadbcd476af30bfff079abe68fcdb Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sun, 27 May 2018 12:24:10 +0100 Subject: bpf: add selftest for lirc_mode2 type program This is simple test over rc-loopback. Acked-by: Yonghong Song Signed-off-by: Sean Young Signed-off-by: Daniel Borkmann --- tools/bpf/bpftool/prog.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/bpf/bpftool/prog.c') diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 39b88e760367..a4f435203fef 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -71,6 +71,7 @@ static const char * const prog_type_name[] = { [BPF_PROG_TYPE_SK_MSG] = "sk_msg", [BPF_PROG_TYPE_RAW_TRACEPOINT] = "raw_tracepoint", [BPF_PROG_TYPE_CGROUP_SOCK_ADDR] = "cgroup_sock_addr", + [BPF_PROG_TYPE_LIRC_MODE2] = "lirc_mode2", }; static void print_boot_time(__u64 nsecs, char *buf, unsigned int size) -- cgit v1.2.3