From 327e5dab6dd8559ba28739ec8873350d7b5bb080 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Fri, 30 Nov 2018 16:25:44 +0000 Subject: tools: bpftool: use "/proc/self/" i.o. crafting links with getpid() The getpid() function is called in a couple of places in bpftool to craft links of the shape "/proc//...". Instead, it is possible to use the "/proc/self/" shortcut, which makes things a bit easier, in particular in jit_disasm.c. Do the replacement, and remove the includes of from the relevant files, now we do not use getpid() anymore. Signed-off-by: Quentin Monnet Reviewed-by: Jakub Kicinski Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/common.c | 5 ++--- tools/bpf/bpftool/jit_disasm.c | 11 +---------- 2 files changed, 3 insertions(+), 13 deletions(-) (limited to 'tools/bpf') diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c index 4e217d57118e..4349b6683ca8 100644 --- a/tools/bpf/bpftool/common.c +++ b/tools/bpf/bpftool/common.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include @@ -276,7 +275,7 @@ int get_fd_type(int fd) char buf[512]; ssize_t n; - snprintf(path, sizeof(path), "/proc/%d/fd/%d", getpid(), fd); + snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); n = readlink(path, buf, sizeof(buf)); if (n < 0) { @@ -304,7 +303,7 @@ char *get_fdinfo(int fd, const char *key) ssize_t n; FILE *fdi; - snprintf(path, sizeof(path), "/proc/%d/fdinfo/%d", getpid(), fd); + snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", fd); fdi = fopen(path, "r"); if (!fdi) { diff --git a/tools/bpf/bpftool/jit_disasm.c b/tools/bpf/bpftool/jit_disasm.c index b2ed5ee1af5f..545a92471c33 100644 --- a/tools/bpf/bpftool/jit_disasm.c +++ b/tools/bpf/bpftool/jit_disasm.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -28,20 +27,12 @@ static void get_exec_path(char *tpath, size_t size) { + const char *path = "/proc/self/exe"; ssize_t len; - char *path; - - snprintf(tpath, size, "/proc/%d/exe", (int) getpid()); - tpath[size - 1] = 0; - - path = strdup(tpath); - assert(path); len = readlink(path, tpath, size - 1); assert(len > 0); tpath[len] = 0; - - free(path); } static int oper_count; -- cgit v1.2.3 From cad4977344b35ea116ec5fefe91a76b1dfa113f5 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Fri, 30 Nov 2018 16:25:45 +0000 Subject: tools: bpftool: fix bash completion for bpftool prog (attach|detach) Fix bash completion for "bpftool prog (attach|detach) PROG TYPE MAP" so that the list of indices proposed for MAP are map indices, and not PROG indices. Also use variables for map and prog reference types ("id", "pinned", and "tag" for programs). Fixes: b7d3826c2ed6 ("bpf: bpftool, add support for attaching programs to maps") Signed-off-by: Quentin Monnet Reviewed-by: Jakub Kicinski Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/bash-completion/bpftool | 73 +++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 24 deletions(-) (limited to 'tools/bpf') diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index 45c2db257d2b..b7e6c4f25ad1 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -243,16 +243,20 @@ _bpftool() # Completion depends on object and command in use case $object in prog) - if [[ $command != "load" && $command != "loadall" ]]; then - case $prev in - id) - _bpftool_get_prog_ids - return 0 - ;; - esac - fi + # Complete id, only for subcommands that use prog (but no map) ids + case $command in + show|list|dump|pin) + case $prev in + id) + _bpftool_get_prog_ids + return 0 + ;; + esac + ;; + esac local PROG_TYPE='id pinned tag' + local MAP_TYPE='id pinned' case $command in show|list) [[ $prev != "$command" ]] && return 0 @@ -293,22 +297,43 @@ _bpftool() return 0 ;; attach|detach) - if [[ ${#words[@]} == 7 ]]; then - COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) ) - return 0 - fi - - if [[ ${#words[@]} == 6 ]]; then - COMPREPLY=( $( compgen -W "msg_verdict skb_verdict \ - skb_parse flow_dissector" -- "$cur" ) ) - return 0 - fi - - if [[ $prev == "$command" ]]; then - COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) ) - return 0 - fi - return 0 + case $cword in + 3) + COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) + return 0 + ;; + 4) + case $prev in + id) + _bpftool_get_prog_ids + ;; + pinned) + _filedir + ;; + esac + return 0 + ;; + 5) + COMPREPLY=( $( compgen -W 'msg_verdict skb_verdict \ + skb_parse flow_dissector' -- "$cur" ) ) + return 0 + ;; + 6) + COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) + return 0 + ;; + 7) + case $prev in + id) + _bpftool_get_map_ids + ;; + pinned) + _filedir + ;; + esac + return 0 + ;; + esac ;; load|loadall) local obj -- cgit v1.2.3 From 4f0fc6f571d29837bc09aa8c51591f330f17bbf0 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Fri, 30 Nov 2018 16:25:46 +0000 Subject: tools: bpftool: fix bash completion for new map types (queue and stack) Commit 197c2dac74e4 ("bpf: Add BPF_MAP_TYPE_QUEUE and BPF_MAP_TYPE_STACK to bpftool-map") added support for queue and stack eBPF map types in bpftool map handling. Let's update the bash completion accordingly. Fixes: 197c2dac74e4 ("bpf: Add BPF_MAP_TYPE_QUEUE and BPF_MAP_TYPE_STACK to bpftool-map") Signed-off-by: Quentin Monnet Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/bash-completion/bpftool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/bpf') diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index b7e6c4f25ad1..9a60080f085f 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -436,7 +436,7 @@ _bpftool() lru_percpu_hash lpm_trie array_of_maps \ hash_of_maps devmap sockmap cpumap xskmap \ sockhash cgroup_storage reuseport_sockarray \ - percpu_cgroup_storage' -- \ + percpu_cgroup_storage queue stack' -- \ "$cur" ) ) return 0 ;; -- cgit v1.2.3 From 73f0b9db53836a68c40691fad1467ed44a3123e8 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Fri, 30 Nov 2018 16:25:47 +0000 Subject: tools: bpftool: mark offloaded programs more explicitly in plain output In bpftool (plain) output for "bpftool prog show" or "bpftool map show", an offloaded BPF object is simply denoted with "dev ifname", which is not really explicit. Change it with something that clearly shows the program is offloaded. While at it also add an additional space, as done between other information fields. Example output, before: # bpftool prog show 1337: xdp tag a04f5eef06a7f555 dev foo loaded_at 2018-10-19T16:40:36+0100 uid 0 xlated 16B not jited memlock 4096B After: # bpftool prog show 1337: xdp tag a04f5eef06a7f555 offloaded_to foo loaded_at 2018-10-19T16:40:36+0100 uid 0 xlated 16B not jited memlock 4096B Suggested-by: Daniel Borkmann Signed-off-by: Quentin Monnet Acked-by: Jakub Kicinski Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/bpf') diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c index 4349b6683ca8..172d3761d9ab 100644 --- a/tools/bpf/bpftool/common.c +++ b/tools/bpf/bpftool/common.c @@ -604,7 +604,7 @@ void print_dev_plain(__u32 ifindex, __u64 ns_dev, __u64 ns_inode) if (!ifindex) return; - printf(" dev "); + printf(" offloaded_to "); if (ifindex_to_name_ns(ifindex, ns_dev, ns_inode, name)) printf("%s", name); else -- cgit v1.2.3 From 99a44bef587082fbbaddf6aaa1e823ebbb629339 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Fri, 30 Nov 2018 16:25:48 +0000 Subject: tools: bpftool: add owner_prog_type and owner_jited to bpftool output For prog array maps, the type of the owner program, and the JIT-ed state of that program, are available from the file descriptor information under /proc. Add them to "bpftool map show" output. Example output: # bpftool map show 158225: prog_array name jmp_table flags 0x0 key 4B value 4B max_entries 8 memlock 4096B owner_prog_type flow_dissector owner jited # bpftool --json --pretty map show [{ "id": 1337, "type": "prog_array", "name": "jmp_table", "flags": 0, "bytes_key": 4, "bytes_value": 4, "max_entries": 8, "bytes_memlock": 4096, "owner_prog_type": "flow_dissector", "owner_jited": true } ] As we move the table used for associating names to program types, complete it with the missing types (lwt_seg6local and sk_reuseport). Also add missing types to the help message for "bpftool prog" (sk_reuseport and flow_dissector). Suggested-by: Daniel Borkmann Signed-off-by: Quentin Monnet Acked-by: Jakub Kicinski Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/main.h | 26 +++++++++++++++++++++++++ tools/bpf/bpftool/map.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++-- tools/bpf/bpftool/prog.c | 25 +----------------------- 3 files changed, 75 insertions(+), 26 deletions(-) (limited to 'tools/bpf') diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h index 7431669fae0a..2761981669c8 100644 --- a/tools/bpf/bpftool/main.h +++ b/tools/bpf/bpftool/main.h @@ -78,6 +78,32 @@ #define HELP_SPEC_MAP \ "MAP := { id MAP_ID | pinned FILE }" +static const char * const prog_type_name[] = { + [BPF_PROG_TYPE_UNSPEC] = "unspec", + [BPF_PROG_TYPE_SOCKET_FILTER] = "socket_filter", + [BPF_PROG_TYPE_KPROBE] = "kprobe", + [BPF_PROG_TYPE_SCHED_CLS] = "sched_cls", + [BPF_PROG_TYPE_SCHED_ACT] = "sched_act", + [BPF_PROG_TYPE_TRACEPOINT] = "tracepoint", + [BPF_PROG_TYPE_XDP] = "xdp", + [BPF_PROG_TYPE_PERF_EVENT] = "perf_event", + [BPF_PROG_TYPE_CGROUP_SKB] = "cgroup_skb", + [BPF_PROG_TYPE_CGROUP_SOCK] = "cgroup_sock", + [BPF_PROG_TYPE_LWT_IN] = "lwt_in", + [BPF_PROG_TYPE_LWT_OUT] = "lwt_out", + [BPF_PROG_TYPE_LWT_XMIT] = "lwt_xmit", + [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", + [BPF_PROG_TYPE_LWT_SEG6LOCAL] = "lwt_seg6local", + [BPF_PROG_TYPE_LIRC_MODE2] = "lirc_mode2", + [BPF_PROG_TYPE_SK_REUSEPORT] = "sk_reuseport", + [BPF_PROG_TYPE_FLOW_DISSECTOR] = "flow_dissector", +}; + enum bpf_obj_type { BPF_OBJ_UNKNOWN, BPF_OBJ_PROG, diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index 3850f8d65703..8469ea6cf1c8 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -487,7 +487,6 @@ static int show_map_close_json(int fd, struct bpf_map_info *info) char *memlock; memlock = get_fdinfo(fd, "memlock"); - close(fd); jsonw_start_object(json_wtr); @@ -514,6 +513,30 @@ static int show_map_close_json(int fd, struct bpf_map_info *info) jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock)); free(memlock); + if (info->type == BPF_MAP_TYPE_PROG_ARRAY) { + char *owner_prog_type = get_fdinfo(fd, "owner_prog_type"); + char *owner_jited = get_fdinfo(fd, "owner_jited"); + + if (owner_prog_type) { + unsigned int prog_type = atoi(owner_prog_type); + + if (prog_type < ARRAY_SIZE(prog_type_name)) + jsonw_string_field(json_wtr, "owner_prog_type", + prog_type_name[prog_type]); + else + jsonw_uint_field(json_wtr, "owner_prog_type", + prog_type); + } + if (atoi(owner_jited)) + jsonw_bool_field(json_wtr, "owner_jited", true); + else + jsonw_bool_field(json_wtr, "owner_jited", false); + + free(owner_prog_type); + free(owner_jited); + } + close(fd); + if (!hash_empty(map_table.table)) { struct pinned_obj *obj; @@ -536,7 +559,6 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info) char *memlock; memlock = get_fdinfo(fd, "memlock"); - close(fd); printf("%u: ", info->id); if (info->type < ARRAY_SIZE(map_type_name)) @@ -557,6 +579,30 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info) printf(" memlock %sB", memlock); free(memlock); + if (info->type == BPF_MAP_TYPE_PROG_ARRAY) { + char *owner_prog_type = get_fdinfo(fd, "owner_prog_type"); + char *owner_jited = get_fdinfo(fd, "owner_jited"); + + printf("\n\t"); + if (owner_prog_type) { + unsigned int prog_type = atoi(owner_prog_type); + + if (prog_type < ARRAY_SIZE(prog_type_name)) + printf("owner_prog_type %s ", + prog_type_name[prog_type]); + else + printf("owner_prog_type %d ", prog_type); + } + if (atoi(owner_jited)) + printf("owner jited"); + else + printf("owner not jited"); + + free(owner_prog_type); + free(owner_jited); + } + close(fd); + printf("\n"); if (!hash_empty(map_table.table)) { struct pinned_obj *obj; diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 4e04699a2350..56db61c5a91f 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -54,30 +54,6 @@ #include "main.h" #include "xlated_dumper.h" -static const char * const prog_type_name[] = { - [BPF_PROG_TYPE_UNSPEC] = "unspec", - [BPF_PROG_TYPE_SOCKET_FILTER] = "socket_filter", - [BPF_PROG_TYPE_KPROBE] = "kprobe", - [BPF_PROG_TYPE_SCHED_CLS] = "sched_cls", - [BPF_PROG_TYPE_SCHED_ACT] = "sched_act", - [BPF_PROG_TYPE_TRACEPOINT] = "tracepoint", - [BPF_PROG_TYPE_XDP] = "xdp", - [BPF_PROG_TYPE_PERF_EVENT] = "perf_event", - [BPF_PROG_TYPE_CGROUP_SKB] = "cgroup_skb", - [BPF_PROG_TYPE_CGROUP_SOCK] = "cgroup_sock", - [BPF_PROG_TYPE_LWT_IN] = "lwt_in", - [BPF_PROG_TYPE_LWT_OUT] = "lwt_out", - [BPF_PROG_TYPE_LWT_XMIT] = "lwt_xmit", - [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", - [BPF_PROG_TYPE_LIRC_MODE2] = "lirc_mode2", - [BPF_PROG_TYPE_FLOW_DISSECTOR] = "flow_dissector", -}; - static const char * const attach_type_strings[] = { [BPF_SK_SKB_STREAM_PARSER] = "stream_parser", [BPF_SK_SKB_STREAM_VERDICT] = "stream_verdict", @@ -1172,6 +1148,7 @@ static int do_help(int argc, char **argv) " tracepoint | raw_tracepoint | xdp | perf_event | cgroup/skb |\n" " cgroup/sock | cgroup/dev | lwt_in | lwt_out | lwt_xmit |\n" " lwt_seg6local | sockops | sk_skb | sk_msg | lirc_mode2 |\n" + " sk_reuseport | flow_dissector |\n" " cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n" " cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n" " cgroup/sendmsg4 | cgroup/sendmsg6 }\n" -- cgit v1.2.3 From 30da46b5dc3a9a14db11706d841440e28b12bb53 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Wed, 5 Dec 2018 10:28:24 +0000 Subject: tools: bpftool: add a command to dump the trace pipe BPF programs can use the bpf_trace_printk() helper to print debug information into the trace pipe. Add a subcommand "bpftool prog tracelog" to simply dump this pipe to the console. This is for a good part copied from iproute2, where the feature is available with "tc exec bpf dbg". Changes include dumping pipe content to stdout instead of stderr and adding JSON support (content is dumped as an array of strings, one per line read from the pipe). This version is dual-licensed, with Daniel's permission. Cc: Daniel Borkmann Suggested-by: Daniel Borkmann Signed-off-by: Quentin Monnet Reviewed-by: Jakub Kicinski Signed-off-by: Daniel Borkmann --- tools/bpf/bpftool/Documentation/bpftool-prog.rst | 13 +- tools/bpf/bpftool/bash-completion/bpftool | 5 +- tools/bpf/bpftool/main.h | 1 + tools/bpf/bpftool/prog.c | 4 +- tools/bpf/bpftool/tracelog.c | 157 +++++++++++++++++++++++ 5 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 tools/bpf/bpftool/tracelog.c (limited to 'tools/bpf') diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst index ab36e920e552..5524b6dccd85 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst @@ -26,8 +26,9 @@ MAP COMMANDS | **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}] | **bpftool** **prog pin** *PROG* *FILE* | **bpftool** **prog { load | loadall }** *OBJ* *PATH* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] -| **bpftool** **prog attach** *PROG* *ATTACH_TYPE* [*MAP*] -| **bpftool** **prog detach** *PROG* *ATTACH_TYPE* [*MAP*] +| **bpftool** **prog attach** *PROG* *ATTACH_TYPE* [*MAP*] +| **bpftool** **prog detach** *PROG* *ATTACH_TYPE* [*MAP*] +| **bpftool** **prog tracelog** | **bpftool** **prog help** | | *MAP* := { **id** *MAP_ID* | **pinned** *FILE* } @@ -117,6 +118,14 @@ DESCRIPTION parameter, with the exception of *flow_dissector* which is detached from the current networking name space. + **bpftool prog tracelog** + Dump the trace pipe of the system to the console (stdout). + Hit to stop printing. BPF programs can write to this + trace pipe at runtime with the **bpf_trace_printk()** helper. + This should be used only for debugging purposes. For + streaming data from BPF programs to user space, one can use + perf events (see also **bpftool-map**\ (8)). + **bpftool prog help** Print short help message. diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index 9a60080f085f..44c189ba072a 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -398,10 +398,13 @@ _bpftool() ;; esac ;; + tracelog) + return 0 + ;; *) [[ $prev == $object ]] && \ COMPREPLY=( $( compgen -W 'dump help pin attach detach load \ - show list' -- "$cur" ) ) + show list tracelog' -- "$cur" ) ) ;; esac ;; diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h index 2761981669c8..0be0dd8f467f 100644 --- a/tools/bpf/bpftool/main.h +++ b/tools/bpf/bpftool/main.h @@ -167,6 +167,7 @@ int do_event_pipe(int argc, char **argv); int do_cgroup(int argc, char **arg); int do_perf(int argc, char **arg); int do_net(int argc, char **arg); +int do_tracelog(int argc, char **arg); int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what); int prog_parse_fd(int *argc, char ***argv); diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 56db61c5a91f..54c8dbf05c9c 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -1140,6 +1140,7 @@ static int do_help(int argc, char **argv) " [pinmaps MAP_DIR]\n" " %s %s attach PROG ATTACH_TYPE [MAP]\n" " %s %s detach PROG ATTACH_TYPE [MAP]\n" + " %s %s tracelog\n" " %s %s help\n" "\n" " " HELP_SPEC_MAP "\n" @@ -1158,7 +1159,7 @@ static int do_help(int argc, char **argv) "", bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], - bin_name, argv[-2], bin_name, argv[-2]); + bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]); return 0; } @@ -1173,6 +1174,7 @@ static const struct cmd cmds[] = { { "loadall", do_loadall }, { "attach", do_attach }, { "detach", do_detach }, + { "tracelog", do_tracelog }, { 0 } }; diff --git a/tools/bpf/bpftool/tracelog.c b/tools/bpf/bpftool/tracelog.c new file mode 100644 index 000000000000..1fa8e513f590 --- /dev/null +++ b/tools/bpf/bpftool/tracelog.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* Copyright (c) 2015-2017 Daniel Borkmann */ +/* Copyright (c) 2018 Netronome Systems, Inc. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "main.h" + +#ifndef TRACEFS_MAGIC +# define TRACEFS_MAGIC 0x74726163 +#endif + +#define _textify(x) #x +#define textify(x) _textify(x) + +FILE *trace_pipe_fd; +char *buff; + +static int validate_tracefs_mnt(const char *mnt, unsigned long magic) +{ + struct statfs st_fs; + + if (statfs(mnt, &st_fs) < 0) + return -ENOENT; + if ((unsigned long)st_fs.f_type != magic) + return -ENOENT; + + return 0; +} + +static bool +find_tracefs_mnt_single(unsigned long magic, char *mnt, const char *mntpt) +{ + size_t src_len; + + if (validate_tracefs_mnt(mntpt, magic)) + return false; + + src_len = strlen(mntpt); + if (src_len + 1 >= PATH_MAX) { + p_err("tracefs mount point name too long"); + return false; + } + + strcpy(mnt, mntpt); + return true; +} + +static bool find_tracefs_pipe(char *mnt) +{ + static const char * const known_mnts[] = { + "/sys/kernel/debug/tracing", + "/sys/kernel/tracing", + "/tracing", + "/trace", + }; + const char *pipe_name = "/trace_pipe"; + const char *fstype = "tracefs"; + char type[100], format[32]; + const char * const *ptr; + bool found = false; + FILE *fp; + + for (ptr = known_mnts; ptr < known_mnts + ARRAY_SIZE(known_mnts); ptr++) + if (find_tracefs_mnt_single(TRACEFS_MAGIC, mnt, *ptr)) + goto exit_found; + + fp = fopen("/proc/mounts", "r"); + if (!fp) + return false; + + /* Allow room for NULL terminating byte and pipe file name */ + snprintf(format, sizeof(format), "%%*s %%%zds %%99s %%*s %%*d %%*d\\n", + PATH_MAX - strlen(pipe_name) - 1); + while (fscanf(fp, format, mnt, type) == 2) + if (strcmp(type, fstype) == 0) { + found = true; + break; + } + fclose(fp); + + /* The string from fscanf() might be truncated, check mnt is valid */ + if (!found || validate_tracefs_mnt(mnt, TRACEFS_MAGIC)) + return false; + +exit_found: + strcat(mnt, pipe_name); + return true; +} + +static void exit_tracelog(int signum) +{ + fclose(trace_pipe_fd); + free(buff); + + if (json_output) { + jsonw_end_array(json_wtr); + jsonw_destroy(&json_wtr); + } + + exit(0); +} + +int do_tracelog(int argc, char **argv) +{ + const struct sigaction act = { + .sa_handler = exit_tracelog + }; + char trace_pipe[PATH_MAX]; + bool found_trace_pipe; + size_t buff_len = 0; + + if (json_output) + jsonw_start_array(json_wtr); + + found_trace_pipe = find_tracefs_pipe(trace_pipe); + if (!found_trace_pipe) { + p_err("could not find trace pipe, tracefs not mounted?"); + return -1; + } + + trace_pipe_fd = fopen(trace_pipe, "r"); + if (!trace_pipe_fd) { + p_err("could not open trace pipe: %s", strerror(errno)); + return -1; + } + + sigaction(SIGHUP, &act, NULL); + sigaction(SIGINT, &act, NULL); + sigaction(SIGTERM, &act, NULL); + while (1) { + ssize_t ret; + + ret = getline(&buff, &buff_len, trace_pipe_fd); + if (ret <= 0) { + p_err("failed to read content from trace pipe: %s", + strerror(errno)); + break; + } + if (json_output) + jsonw_string(json_wtr, buff); + else + printf("%s", buff); + } + + fclose(trace_pipe_fd); + free(buff); + return -1; +} -- cgit v1.2.3 From 84ecc1f98ca7ce28ede9bc5cc70a557fdfa09caa Mon Sep 17 00:00:00 2001 From: Martin KaFai Lau Date: Wed, 5 Dec 2018 17:35:47 -0800 Subject: bpf: Expect !info.func_info and insn_off name changes in test_btf/libbpf/bpftool Similar to info.jited_*, info.func_info could be 0 if bpf_dump_raw_ok() == false. This patch makes changes to test_btf and bpftool to expect info.func_info could be 0. This patch also makes the needed changes for s/insn_offset/insn_off/. Signed-off-by: Martin KaFai Lau Acked-by: Yonghong Song Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/prog.c | 7 +++++++ tools/bpf/bpftool/xlated_dumper.c | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'tools/bpf') diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 54c8dbf05c9c..a9a51123454c 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -589,6 +589,13 @@ static int do_dump(int argc, char **argv) goto err_free; } + if (func_info && !info.func_info) { + /* kernel.kptr_restrict is set. No func_info available. */ + free(func_info); + func_info = NULL; + finfo_cnt = 0; + } + if ((member_len == &info.jited_prog_len && info.jited_prog_insns == 0) || (member_len == &info.xlated_prog_len && diff --git a/tools/bpf/bpftool/xlated_dumper.c b/tools/bpf/bpftool/xlated_dumper.c index e06ac0286a75..131ecd175533 100644 --- a/tools/bpf/bpftool/xlated_dumper.c +++ b/tools/bpf/bpftool/xlated_dumper.c @@ -261,7 +261,7 @@ void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len, jsonw_start_object(json_wtr); if (btf && record) { - if (record->insn_offset == i) { + if (record->insn_off == i) { btf_dumper_type_only(btf, record->type_id, func_sig, sizeof(func_sig)); @@ -330,7 +330,7 @@ void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len, } if (btf && record) { - if (record->insn_offset == i) { + if (record->insn_off == i) { btf_dumper_type_only(btf, record->type_id, func_sig, sizeof(func_sig)); -- cgit v1.2.3 From b053b439b72ad152257ecc3f71cfb4c619b0137e Mon Sep 17 00:00:00 2001 From: Martin KaFai Lau Date: Fri, 7 Dec 2018 16:42:32 -0800 Subject: bpf: libbpf: bpftool: Print bpf_line_info during prog dump This patch adds print bpf_line_info function in 'prog dump jitted' and 'prog dump xlated': [root@arch-fb-vm1 bpf]# ~/devshare/fb-kernel/linux/tools/bpf/bpftool/bpftool prog dump jited pinned /sys/fs/bpf/test_btf_haskv [...] int test_long_fname_2(struct dummy_tracepoint_args * arg): bpf_prog_44a040bf25481309_test_long_fname_2: ; static int test_long_fname_2(struct dummy_tracepoint_args *arg) 0: push %rbp 1: mov %rsp,%rbp 4: sub $0x30,%rsp b: sub $0x28,%rbp f: mov %rbx,0x0(%rbp) 13: mov %r13,0x8(%rbp) 17: mov %r14,0x10(%rbp) 1b: mov %r15,0x18(%rbp) 1f: xor %eax,%eax 21: mov %rax,0x20(%rbp) 25: xor %esi,%esi ; int key = 0; 27: mov %esi,-0x4(%rbp) ; if (!arg->sock) 2a: mov 0x8(%rdi),%rdi ; if (!arg->sock) 2e: cmp $0x0,%rdi 32: je 0x0000000000000070 34: mov %rbp,%rsi ; counts = bpf_map_lookup_elem(&btf_map, &key); 37: add $0xfffffffffffffffc,%rsi 3b: movabs $0xffff8881139d7480,%rdi 45: add $0x110,%rdi 4c: mov 0x0(%rsi),%eax 4f: cmp $0x4,%rax 53: jae 0x000000000000005e 55: shl $0x3,%rax 59: add %rdi,%rax 5c: jmp 0x0000000000000060 5e: xor %eax,%eax ; if (!counts) 60: cmp $0x0,%rax 64: je 0x0000000000000070 ; counts->v6++; 66: mov 0x4(%rax),%edi 69: add $0x1,%rdi 6d: mov %edi,0x4(%rax) 70: mov 0x0(%rbp),%rbx 74: mov 0x8(%rbp),%r13 78: mov 0x10(%rbp),%r14 7c: mov 0x18(%rbp),%r15 80: add $0x28,%rbp 84: leaveq 85: retq [...] With linum: [root@arch-fb-vm1 bpf]# ~/devshare/fb-kernel/linux/tools/bpf/bpftool/bpftool prog dump jited pinned /sys/fs/bpf/test_btf_haskv linum int _dummy_tracepoint(struct dummy_tracepoint_args * arg): bpf_prog_b07ccb89267cf242__dummy_tracepoint: ; return test_long_fname_1(arg); [file:/data/users/kafai/fb-kernel/linux/tools/testing/selftests/bpf/test_btf_haskv.c line_num:54 line_col:9] 0: push %rbp 1: mov %rsp,%rbp 4: sub $0x28,%rsp b: sub $0x28,%rbp f: mov %rbx,0x0(%rbp) 13: mov %r13,0x8(%rbp) 17: mov %r14,0x10(%rbp) 1b: mov %r15,0x18(%rbp) 1f: xor %eax,%eax 21: mov %rax,0x20(%rbp) 25: callq 0x000000000000851e ; return test_long_fname_1(arg); [file:/data/users/kafai/fb-kernel/linux/tools/testing/selftests/bpf/test_btf_haskv.c line_num:54 line_col:2] 2a: xor %eax,%eax 2c: mov 0x0(%rbp),%rbx 30: mov 0x8(%rbp),%r13 34: mov 0x10(%rbp),%r14 38: mov 0x18(%rbp),%r15 3c: add $0x28,%rbp 40: leaveq 41: retq [...] Signed-off-by: Martin KaFai Lau Acked-by: Yonghong Song Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/Documentation/bpftool-prog.rst | 16 +++- tools/bpf/bpftool/bash-completion/bpftool | 6 +- tools/bpf/bpftool/btf_dumper.c | 64 +++++++++++++++ tools/bpf/bpftool/jit_disasm.c | 23 +++++- tools/bpf/bpftool/main.h | 23 +++++- tools/bpf/bpftool/prog.c | 100 ++++++++++++++++++++--- tools/bpf/bpftool/xlated_dumper.c | 30 ++++++- tools/bpf/bpftool/xlated_dumper.h | 7 +- 8 files changed, 245 insertions(+), 24 deletions(-) (limited to 'tools/bpf') diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst index 5524b6dccd85..7c30731a9b73 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst @@ -22,8 +22,8 @@ MAP COMMANDS ============= | **bpftool** **prog { show | list }** [*PROG*] -| **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes** | **visual**}] -| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}] +| **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes** | **visual** | **linum**}] +| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes** | **linum**}] | **bpftool** **prog pin** *PROG* *FILE* | **bpftool** **prog { load | loadall }** *OBJ* *PATH* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] | **bpftool** **prog attach** *PROG* *ATTACH_TYPE* [*MAP*] @@ -56,7 +56,7 @@ DESCRIPTION Output will start with program ID followed by program type and zero or more named attributes (depending on kernel version). - **bpftool prog dump xlated** *PROG* [{ **file** *FILE* | **opcodes** | **visual** }] + **bpftool prog dump xlated** *PROG* [{ **file** *FILE* | **opcodes** | **visual** | **linum** }] Dump eBPF instructions of the program from the kernel. By default, eBPF will be disassembled and printed to standard output in human-readable format. In this case, **opcodes** @@ -69,13 +69,21 @@ DESCRIPTION built instead, and eBPF instructions will be presented with CFG in DOT format, on standard output. - **bpftool prog dump jited** *PROG* [{ **file** *FILE* | **opcodes** }] + If the prog has line_info available, the source line will + be displayed by default. If **linum** is specified, + the filename, line number and line column will also be + displayed on top of the source line. + **bpftool prog dump jited** *PROG* [{ **file** *FILE* | **opcodes** | **linum** }] Dump jited image (host machine code) of the program. If *FILE* is specified image will be written to a file, otherwise it will be disassembled and printed to stdout. **opcodes** controls if raw opcodes will be printed. + If the prog has line_info available, the source line will + be displayed by default. If **linum** is specified, + the filename, line number and line column will also be + displayed on top of the source line. **bpftool prog pin** *PROG* *FILE* Pin program *PROG* as *FILE*. diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index 44c189ba072a..a57febd6abb1 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -191,7 +191,7 @@ _bpftool() # Deal with simplest keywords case $prev in - help|hex|opcodes|visual) + help|hex|opcodes|visual|linum) return 0 ;; tag) @@ -278,10 +278,10 @@ _bpftool() *) _bpftool_once_attr 'file' if _bpftool_search_list 'xlated'; then - COMPREPLY+=( $( compgen -W 'opcodes visual' -- \ + COMPREPLY+=( $( compgen -W 'opcodes visual linum' -- \ "$cur" ) ) else - COMPREPLY+=( $( compgen -W 'opcodes' -- \ + COMPREPLY+=( $( compgen -W 'opcodes linum' -- \ "$cur" ) ) fi return 0 diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c index c3fd3a7cb787..dbbf6ece6760 100644 --- a/tools/bpf/bpftool/btf_dumper.c +++ b/tools/bpf/bpftool/btf_dumper.c @@ -385,3 +385,67 @@ void btf_dumper_type_only(const struct btf *btf, __u32 type_id, char *func_sig, if (err < 0) func_sig[0] = '\0'; } + +static const char *ltrim(const char *s) +{ + while (isspace(*s)) + s++; + + return s; +} + +void btf_dump_linfo_plain(const struct btf *btf, + const struct bpf_line_info *linfo, + const char *prefix, bool linum) +{ + const char *line = btf__name_by_offset(btf, linfo->line_off); + + if (!line) + return; + line = ltrim(line); + + if (!prefix) + prefix = ""; + + if (linum) { + const char *file = btf__name_by_offset(btf, linfo->file_name_off); + + /* More forgiving on file because linum option is + * expected to provide more info than the already + * available src line. + */ + if (!file) + file = ""; + + printf("%s%s [file:%s line_num:%u line_col:%u]\n", + prefix, line, file, + BPF_LINE_INFO_LINE_NUM(linfo->line_col), + BPF_LINE_INFO_LINE_COL(linfo->line_col)); + } else { + printf("%s%s\n", prefix, line); + } +} + +void btf_dump_linfo_json(const struct btf *btf, + const struct bpf_line_info *linfo, bool linum) +{ + const char *line = btf__name_by_offset(btf, linfo->line_off); + + if (line) + jsonw_string_field(json_wtr, "src", ltrim(line)); + + if (linum) { + const char *file = btf__name_by_offset(btf, linfo->file_name_off); + + if (file) + jsonw_string_field(json_wtr, "file", file); + + if (BPF_LINE_INFO_LINE_NUM(linfo->line_col)) + jsonw_int_field(json_wtr, "line_num", + BPF_LINE_INFO_LINE_NUM(linfo->line_col)); + + if (BPF_LINE_INFO_LINE_COL(linfo->line_col)) + jsonw_int_field(json_wtr, "line_col", + BPF_LINE_INFO_LINE_COL(linfo->line_col)); + } +} diff --git a/tools/bpf/bpftool/jit_disasm.c b/tools/bpf/bpftool/jit_disasm.c index 545a92471c33..f381f8628ce9 100644 --- a/tools/bpf/bpftool/jit_disasm.c +++ b/tools/bpf/bpftool/jit_disasm.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "json_writer.h" #include "main.h" @@ -68,10 +69,16 @@ static int fprintf_json(void *out, const char *fmt, ...) } void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, - const char *arch, const char *disassembler_options) + const char *arch, const char *disassembler_options, + const struct btf *btf, + const struct bpf_prog_linfo *prog_linfo, + __u64 func_ksym, unsigned int func_idx, + bool linum) { + const struct bpf_line_info *linfo = NULL; disassembler_ftype disassemble; struct disassemble_info info; + unsigned int nr_skip = 0; int count, i, pc = 0; char tpath[PATH_MAX]; bfd *bfdf; @@ -127,12 +134,26 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, if (json_output) jsonw_start_array(json_wtr); do { + if (prog_linfo) { + linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo, + func_ksym + pc, + func_idx, + nr_skip); + if (linfo) + nr_skip++; + } + if (json_output) { jsonw_start_object(json_wtr); oper_count = 0; + if (linfo) + btf_dump_linfo_json(btf, linfo, linum); jsonw_name(json_wtr, "pc"); jsonw_printf(json_wtr, "\"0x%x\"", pc); } else { + if (linfo) + btf_dump_linfo_plain(btf, linfo, "; ", + linum); printf("%4x:\t", pc); } diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h index 0be0dd8f467f..d9393abdba78 100644 --- a/tools/bpf/bpftool/main.h +++ b/tools/bpf/bpftool/main.h @@ -138,6 +138,9 @@ struct pinned_obj { struct hlist_node hash; }; +struct btf; +struct bpf_line_info; + int build_pinned_obj_table(struct pinned_obj_table *table, enum bpf_obj_type type); void delete_pinned_obj_table(struct pinned_obj_table *tab); @@ -175,13 +178,23 @@ int map_parse_fd(int *argc, char ***argv); int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len); #ifdef HAVE_LIBBFD_SUPPORT +struct bpf_prog_linfo; void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, - const char *arch, const char *disassembler_options); + const char *arch, const char *disassembler_options, + const struct btf *btf, + const struct bpf_prog_linfo *prog_linfo, + __u64 func_ksym, unsigned int func_idx, + bool linum); int disasm_init(void); #else static inline void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, - const char *arch, const char *disassembler_options) + const char *arch, const char *disassembler_options, + const struct btf *btf, + const struct bpf_prog_linfo *prog_linfo, + __u64 func_ksym, unsigned int func_idx, + bool linum) + { } static inline int disasm_init(void) @@ -217,6 +230,12 @@ int btf_dumper_type(const struct btf_dumper *d, __u32 type_id, void btf_dumper_type_only(const struct btf *btf, __u32 func_type_id, char *func_only, int size); +void btf_dump_linfo_plain(const struct btf *btf, + const struct bpf_line_info *linfo, + const char *prefix, bool linum); +void btf_dump_linfo_json(const struct btf *btf, + const struct bpf_line_info *linfo, bool linum); + struct nlattr; struct ifinfomsg; struct tcmsg; diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index a9a51123454c..65b921ffd10a 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -423,24 +423,26 @@ static int do_show(int argc, char **argv) static int do_dump(int argc, char **argv) { + unsigned int finfo_rec_size, linfo_rec_size, jited_linfo_rec_size; + void *func_info = NULL, *linfo = NULL, *jited_linfo = NULL; + unsigned int finfo_cnt, linfo_cnt = 0, jited_linfo_cnt = 0; + struct bpf_prog_linfo *prog_linfo = NULL; unsigned long *func_ksyms = NULL; struct bpf_prog_info info = {}; unsigned int *func_lens = NULL; const char *disasm_opt = NULL; - unsigned int finfo_rec_size; unsigned int nr_func_ksyms; unsigned int nr_func_lens; struct dump_data dd = {}; __u32 len = sizeof(info); struct btf *btf = NULL; - void *func_info = NULL; - unsigned int finfo_cnt; unsigned int buf_size; char *filepath = NULL; bool opcodes = false; bool visual = false; char func_sig[1024]; unsigned char *buf; + bool linum = false; __u32 *member_len; __u64 *member_ptr; ssize_t n; @@ -484,6 +486,9 @@ static int do_dump(int argc, char **argv) } else if (is_prefix(*argv, "visual")) { visual = true; NEXT_ARG(); + } else if (is_prefix(*argv, "linum")) { + linum = true; + NEXT_ARG(); } if (argc) { @@ -543,6 +548,32 @@ static int do_dump(int argc, char **argv) } } + linfo_rec_size = info.line_info_rec_size; + if (info.line_info_cnt && linfo_rec_size && info.btf_id) { + linfo_cnt = info.line_info_cnt; + linfo = malloc(linfo_cnt * linfo_rec_size); + if (!linfo) { + p_err("mem alloc failed"); + close(fd); + goto err_free; + } + } + + jited_linfo_rec_size = info.jited_line_info_rec_size; + if (info.jited_line_info_cnt && + jited_linfo_rec_size && + info.nr_jited_ksyms && + info.nr_jited_func_lens && + info.btf_id) { + jited_linfo_cnt = info.jited_line_info_cnt; + jited_linfo = malloc(jited_linfo_cnt * jited_linfo_rec_size); + if (!jited_linfo) { + p_err("mem alloc failed"); + close(fd); + goto err_free; + } + } + memset(&info, 0, sizeof(info)); *member_ptr = ptr_to_u64(buf); @@ -554,6 +585,13 @@ static int do_dump(int argc, char **argv) info.func_info_cnt = finfo_cnt; info.func_info_rec_size = finfo_rec_size; info.func_info = ptr_to_u64(func_info); + info.line_info_cnt = linfo_cnt; + info.line_info_rec_size = linfo_rec_size; + info.line_info = ptr_to_u64(linfo); + info.jited_line_info_cnt = jited_linfo_cnt; + info.jited_line_info_rec_size = jited_linfo_rec_size; + info.jited_line_info = ptr_to_u64(jited_linfo); + err = bpf_obj_get_info_by_fd(fd, &info, &len); close(fd); @@ -596,6 +634,30 @@ static int do_dump(int argc, char **argv) finfo_cnt = 0; } + if (linfo && info.line_info_cnt != linfo_cnt) { + p_err("incorrect line_info_cnt %u vs. expected %u", + info.line_info_cnt, linfo_cnt); + goto err_free; + } + + if (info.line_info_rec_size != linfo_rec_size) { + p_err("incorrect line_info_rec_size %u vs. expected %u", + info.line_info_rec_size, linfo_rec_size); + goto err_free; + } + + if (jited_linfo && info.jited_line_info_cnt != jited_linfo_cnt) { + p_err("incorrect jited_line_info_cnt %u vs. expected %u", + info.jited_line_info_cnt, jited_linfo_cnt); + goto err_free; + } + + if (info.jited_line_info_rec_size != jited_linfo_rec_size) { + p_err("incorrect jited_line_info_rec_size %u vs. expected %u", + info.jited_line_info_rec_size, jited_linfo_rec_size); + goto err_free; + } + if ((member_len == &info.jited_prog_len && info.jited_prog_insns == 0) || (member_len == &info.xlated_prog_len && @@ -609,6 +671,12 @@ static int do_dump(int argc, char **argv) goto err_free; } + if (linfo_cnt) { + prog_linfo = bpf_prog_linfo__new(&info); + if (!prog_linfo) + p_err("error in processing bpf_line_info. continue without it."); + } + if (filepath) { fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { @@ -690,8 +758,11 @@ static int do_dump(int argc, char **argv) printf("%s:\n", sym_name); } - disasm_print_insn(img, lens[i], opcodes, name, - disasm_opt); + disasm_print_insn(img, lens[i], opcodes, + name, disasm_opt, btf, + prog_linfo, ksyms[i], i, + linum); + img += lens[i]; if (json_output) @@ -704,7 +775,7 @@ static int do_dump(int argc, char **argv) jsonw_end_array(json_wtr); } else { disasm_print_insn(buf, *member_len, opcodes, name, - disasm_opt); + disasm_opt, btf, NULL, 0, 0, false); } } else if (visual) { if (json_output) @@ -718,11 +789,14 @@ static int do_dump(int argc, char **argv) dd.btf = btf; dd.func_info = func_info; dd.finfo_rec_size = finfo_rec_size; + dd.prog_linfo = prog_linfo; if (json_output) - dump_xlated_json(&dd, buf, *member_len, opcodes); + dump_xlated_json(&dd, buf, *member_len, opcodes, + linum); else - dump_xlated_plain(&dd, buf, *member_len, opcodes); + dump_xlated_plain(&dd, buf, *member_len, opcodes, + linum); kernel_syms_destroy(&dd); } @@ -730,6 +804,9 @@ static int do_dump(int argc, char **argv) free(func_ksyms); free(func_lens); free(func_info); + free(linfo); + free(jited_linfo); + bpf_prog_linfo__free(prog_linfo); return 0; err_free: @@ -737,6 +814,9 @@ err_free: free(func_ksyms); free(func_lens); free(func_info); + free(linfo); + free(jited_linfo); + bpf_prog_linfo__free(prog_linfo); return -1; } @@ -1138,8 +1218,8 @@ static int do_help(int argc, char **argv) fprintf(stderr, "Usage: %s %s { show | list } [PROG]\n" - " %s %s dump xlated PROG [{ file FILE | opcodes | visual }]\n" - " %s %s dump jited PROG [{ file FILE | opcodes }]\n" + " %s %s dump xlated PROG [{ file FILE | opcodes | visual | linum }]\n" + " %s %s dump jited PROG [{ file FILE | opcodes | linum }]\n" " %s %s pin PROG FILE\n" " %s %s { load | loadall } OBJ PATH \\\n" " [type TYPE] [dev NAME] \\\n" diff --git a/tools/bpf/bpftool/xlated_dumper.c b/tools/bpf/bpftool/xlated_dumper.c index 131ecd175533..aef628dcccb6 100644 --- a/tools/bpf/bpftool/xlated_dumper.c +++ b/tools/bpf/bpftool/xlated_dumper.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "disasm.h" #include "json_writer.h" @@ -234,8 +235,9 @@ static const char *print_imm(void *private_data, } void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len, - bool opcodes) + bool opcodes, bool linum) { + const struct bpf_prog_linfo *prog_linfo = dd->prog_linfo; const struct bpf_insn_cbs cbs = { .cb_print = print_insn_json, .cb_call = print_call, @@ -246,6 +248,7 @@ void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len, struct bpf_insn *insn = buf; struct btf *btf = dd->btf; bool double_insn = false; + unsigned int nr_skip = 0; char func_sig[1024]; unsigned int i; @@ -273,6 +276,16 @@ void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len, } } + if (prog_linfo) { + const struct bpf_line_info *linfo; + + linfo = bpf_prog_linfo__lfind(prog_linfo, i, nr_skip); + if (linfo) { + btf_dump_linfo_json(btf, linfo, linum); + nr_skip++; + } + } + jsonw_name(json_wtr, "disasm"); print_bpf_insn(&cbs, insn + i, true); @@ -307,8 +320,9 @@ void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len, } void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len, - bool opcodes) + bool opcodes, bool linum) { + const struct bpf_prog_linfo *prog_linfo = dd->prog_linfo; const struct bpf_insn_cbs cbs = { .cb_print = print_insn, .cb_call = print_call, @@ -318,6 +332,7 @@ void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len, struct bpf_func_info *record; struct bpf_insn *insn = buf; struct btf *btf = dd->btf; + unsigned int nr_skip = 0; bool double_insn = false; char func_sig[1024]; unsigned int i; @@ -340,6 +355,17 @@ void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len, } } + if (prog_linfo) { + const struct bpf_line_info *linfo; + + linfo = bpf_prog_linfo__lfind(prog_linfo, i, nr_skip); + if (linfo) { + btf_dump_linfo_plain(btf, linfo, "; ", + linum); + nr_skip++; + } + } + double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW); printf("% 4d: ", i); diff --git a/tools/bpf/bpftool/xlated_dumper.h b/tools/bpf/bpftool/xlated_dumper.h index aec31723e1e5..a24f89df8cb2 100644 --- a/tools/bpf/bpftool/xlated_dumper.h +++ b/tools/bpf/bpftool/xlated_dumper.h @@ -40,6 +40,8 @@ #define SYM_MAX_NAME 256 +struct bpf_prog_linfo; + struct kernel_sym { unsigned long address; char name[SYM_MAX_NAME]; @@ -54,6 +56,7 @@ struct dump_data { struct btf *btf; void *func_info; __u32 finfo_rec_size; + const struct bpf_prog_linfo *prog_linfo; char scratch_buff[SYM_MAX_NAME + 8]; }; @@ -61,9 +64,9 @@ void kernel_syms_load(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, - bool opcodes); + bool opcodes, bool linum); void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len, - bool opcodes); + bool opcodes, bool linum); void dump_xlated_for_graph(struct dump_data *dd, void *buf, void *buf_end, unsigned int start_index); -- cgit v1.2.3 From 10a5ce98539948affbdc28dc0f39a1b6b2307f9d Mon Sep 17 00:00:00 2001 From: Martin KaFai Lau Date: Mon, 10 Dec 2018 10:53:24 -0800 Subject: bpf: bpftool: Fix newline and p_err issue This patch fixes a few newline issues and also replaces p_err with p_info in prog.c Fixes: b053b439b72a ("bpf: libbpf: bpftool: Print bpf_line_info during prog dump") Cc: Jakub Kicinski Signed-off-by: Martin KaFai Lau Acked-by: Jakub Kicinski Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/Documentation/bpftool-prog.rst | 2 ++ tools/bpf/bpftool/main.h | 1 - tools/bpf/bpftool/prog.c | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'tools/bpf') diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst index 7c30731a9b73..bb1aeb98b6da 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst @@ -73,6 +73,7 @@ DESCRIPTION be displayed by default. If **linum** is specified, the filename, line number and line column will also be displayed on top of the source line. + **bpftool prog dump jited** *PROG* [{ **file** *FILE* | **opcodes** | **linum** }] Dump jited image (host machine code) of the program. If *FILE* is specified image will be written to a file, @@ -84,6 +85,7 @@ DESCRIPTION be displayed by default. If **linum** is specified, the filename, line number and line column will also be displayed on top of the source line. + **bpftool prog pin** *PROG* *FILE* Pin program *PROG* as *FILE*. diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h index d9393abdba78..0b37599f8cda 100644 --- a/tools/bpf/bpftool/main.h +++ b/tools/bpf/bpftool/main.h @@ -194,7 +194,6 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, const struct bpf_prog_linfo *prog_linfo, __u64 func_ksym, unsigned int func_idx, bool linum) - { } static inline int disasm_init(void) diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 65b921ffd10a..9a78ebbcea1d 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -592,7 +592,6 @@ static int do_dump(int argc, char **argv) info.jited_line_info_rec_size = jited_linfo_rec_size; info.jited_line_info = ptr_to_u64(jited_linfo); - err = bpf_obj_get_info_by_fd(fd, &info, &len); close(fd); if (err) { @@ -674,7 +673,7 @@ static int do_dump(int argc, char **argv) if (linfo_cnt) { prog_linfo = bpf_prog_linfo__new(&info); if (!prog_linfo) - p_err("error in processing bpf_line_info. continue without it."); + p_info("error in processing bpf_line_info. continue without it."); } if (filepath) { -- cgit v1.2.3 From cfc542411bd40ff4f8a70b3d061bd6acdfb05629 Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Mon, 10 Dec 2018 14:14:10 -0800 Subject: tools/bpf: rename *_info_cnt to nr_*_info Rename all occurances of *_info_cnt field access to nr_*_info in tools directory. The local variables finfo_cnt, linfo_cnt and jited_linfo_cnt in function do_dump() of tools/bpf/bpftool/prog.c are also changed to nr_finfo, nr_linfo and nr_jited_linfo to keep naming convention consistent. Acked-by: Martin KaFai Lau Signed-off-by: Yonghong Song Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/prog.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'tools/bpf') diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 9a78ebbcea1d..b73b4e473948 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -425,7 +425,7 @@ static int do_dump(int argc, char **argv) { unsigned int finfo_rec_size, linfo_rec_size, jited_linfo_rec_size; void *func_info = NULL, *linfo = NULL, *jited_linfo = NULL; - unsigned int finfo_cnt, linfo_cnt = 0, jited_linfo_cnt = 0; + unsigned int nr_finfo, nr_linfo = 0, nr_jited_linfo = 0; struct bpf_prog_linfo *prog_linfo = NULL; unsigned long *func_ksyms = NULL; struct bpf_prog_info info = {}; @@ -537,10 +537,10 @@ static int do_dump(int argc, char **argv) } } - finfo_cnt = info.func_info_cnt; + nr_finfo = info.nr_func_info; finfo_rec_size = info.func_info_rec_size; - if (finfo_cnt && finfo_rec_size) { - func_info = malloc(finfo_cnt * finfo_rec_size); + if (nr_finfo && finfo_rec_size) { + func_info = malloc(nr_finfo * finfo_rec_size); if (!func_info) { p_err("mem alloc failed"); close(fd); @@ -549,9 +549,9 @@ static int do_dump(int argc, char **argv) } linfo_rec_size = info.line_info_rec_size; - if (info.line_info_cnt && linfo_rec_size && info.btf_id) { - linfo_cnt = info.line_info_cnt; - linfo = malloc(linfo_cnt * linfo_rec_size); + if (info.nr_line_info && linfo_rec_size && info.btf_id) { + nr_linfo = info.nr_line_info; + linfo = malloc(nr_linfo * linfo_rec_size); if (!linfo) { p_err("mem alloc failed"); close(fd); @@ -560,13 +560,13 @@ static int do_dump(int argc, char **argv) } jited_linfo_rec_size = info.jited_line_info_rec_size; - if (info.jited_line_info_cnt && + if (info.nr_jited_line_info && jited_linfo_rec_size && info.nr_jited_ksyms && info.nr_jited_func_lens && info.btf_id) { - jited_linfo_cnt = info.jited_line_info_cnt; - jited_linfo = malloc(jited_linfo_cnt * jited_linfo_rec_size); + nr_jited_linfo = info.nr_jited_line_info; + jited_linfo = malloc(nr_jited_linfo * jited_linfo_rec_size); if (!jited_linfo) { p_err("mem alloc failed"); close(fd); @@ -582,13 +582,13 @@ static int do_dump(int argc, char **argv) info.nr_jited_ksyms = nr_func_ksyms; info.jited_func_lens = ptr_to_u64(func_lens); info.nr_jited_func_lens = nr_func_lens; - info.func_info_cnt = finfo_cnt; + info.nr_func_info = nr_finfo; info.func_info_rec_size = finfo_rec_size; info.func_info = ptr_to_u64(func_info); - info.line_info_cnt = linfo_cnt; + info.nr_line_info = nr_linfo; info.line_info_rec_size = linfo_rec_size; info.line_info = ptr_to_u64(linfo); - info.jited_line_info_cnt = jited_linfo_cnt; + info.nr_jited_line_info = nr_jited_linfo; info.jited_line_info_rec_size = jited_linfo_rec_size; info.jited_line_info = ptr_to_u64(jited_linfo); @@ -614,9 +614,9 @@ static int do_dump(int argc, char **argv) goto err_free; } - if (info.func_info_cnt != finfo_cnt) { - p_err("incorrect func_info_cnt %d vs. expected %d", - info.func_info_cnt, finfo_cnt); + if (info.nr_func_info != nr_finfo) { + p_err("incorrect nr_func_info %d vs. expected %d", + info.nr_func_info, nr_finfo); goto err_free; } @@ -630,12 +630,12 @@ static int do_dump(int argc, char **argv) /* kernel.kptr_restrict is set. No func_info available. */ free(func_info); func_info = NULL; - finfo_cnt = 0; + nr_finfo = 0; } - if (linfo && info.line_info_cnt != linfo_cnt) { - p_err("incorrect line_info_cnt %u vs. expected %u", - info.line_info_cnt, linfo_cnt); + if (linfo && info.nr_line_info != nr_linfo) { + p_err("incorrect nr_line_info %u vs. expected %u", + info.nr_line_info, nr_linfo); goto err_free; } @@ -645,9 +645,9 @@ static int do_dump(int argc, char **argv) goto err_free; } - if (jited_linfo && info.jited_line_info_cnt != jited_linfo_cnt) { - p_err("incorrect jited_line_info_cnt %u vs. expected %u", - info.jited_line_info_cnt, jited_linfo_cnt); + if (jited_linfo && info.nr_jited_line_info != nr_jited_linfo) { + p_err("incorrect nr_jited_line_info %u vs. expected %u", + info.nr_jited_line_info, nr_jited_linfo); goto err_free; } @@ -670,7 +670,7 @@ static int do_dump(int argc, char **argv) goto err_free; } - if (linfo_cnt) { + if (nr_linfo) { prog_linfo = bpf_prog_linfo__new(&info); if (!prog_linfo) p_info("error in processing bpf_line_info. continue without it."); -- cgit v1.2.3