Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b053b439 authored by Martin KaFai Lau's avatar Martin KaFai Lau Committed by Alexei Starovoitov
Browse files

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: default avatarMartin KaFai Lau <kafai@fb.com>
Acked-by: default avatarYonghong Song <yhs@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 3d650141
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -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*.

+3 −3
Original line number Diff line number Diff line
@@ -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
+64 −0
Original line number Diff line number Diff line
@@ -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));
	}
}
+22 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <dis-asm.h>
#include <sys/stat.h>
#include <limits.h>
#include <libbpf.h>

#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);
		}

+21 −2
Original line number Diff line number Diff line
@@ -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;
Loading