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

Commit c9c35995 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller
Browse files

tools: bpftool: use the kernel's instruction printer



Compile the instruction printer from kernel/bpf and use it
for disassembling "translated" eBPF code.

Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarSimon Horman <simon.horman@netronome.com>
Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
Acked-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f4ac7e0b
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@ SYNOPSIS
========

|	**bpftool** prog show [*PROG*]
|	**bpftool** prog dump xlated *PROG*  file *FILE*
|	**bpftool** prog dump xlated *PROG* [file *FILE*] [opcodes]
|	**bpftool** prog dump jited  *PROG* [file *FILE*] [opcodes]
|	**bpftool** prog pin *PROG* *FILE*
|	**bpftool** prog help
@@ -28,9 +28,12 @@ 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*
		  Dump eBPF instructions of the program from the kernel to a
		  file.
	**bpftool prog dump xlated** *PROG* [**file** *FILE*] [**opcodes**]
		  Dump eBPF instructions of the program from the kernel.
		  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.

	**bpftool prog dump jited**  *PROG* [**file** *FILE*] [**opcodes**]
		  Dump jited image (host machine code) of the program.
+5 −2
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ CC = gcc

CFLAGS += -O2
CFLAGS += -W -Wall -Wextra -Wno-unused-parameter -Wshadow
CFLAGS += -D__EXPORTED_HEADERS__ -I$(srctree)/tools/include/uapi -I$(srctree)/tools/include -I$(srctree)/tools/lib/bpf
CFLAGS += -D__EXPORTED_HEADERS__ -I$(srctree)/tools/include/uapi -I$(srctree)/tools/include -I$(srctree)/tools/lib/bpf -I$(srctree)/kernel/bpf/
LIBS = -lelf -lbfd -lopcodes $(LIBBPF)

include $(wildcard *.d)
@@ -59,7 +59,10 @@ include $(wildcard *.d)
all: $(OUTPUT)bpftool

SRCS=$(wildcard *.c)
OBJS=$(patsubst %.c,$(OUTPUT)%.o,$(SRCS))
OBJS=$(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o

$(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c
	$(QUIET_CC)$(COMPILE.c) -MMD -o $@ $<

$(OUTPUT)bpftool: $(OBJS) $(LIBBPF)
	$(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
+3 −7
Original line number Diff line number Diff line
@@ -36,11 +36,12 @@
#ifndef __BPF_TOOL_H
#define __BPF_TOOL_H

/* BFD and kernel.h both define GCC_VERSION, differently */
#undef GCC_VERSION
#include <stdbool.h>
#include <stdio.h>
#include <linux/bpf.h>

#define ARRAY_SIZE(a)	(sizeof(a) / sizeof(a[0]))
#include <linux/kernel.h>

#define err(msg...)	fprintf(stderr, "Error: " msg)
#define warn(msg...)	fprintf(stderr, "Warning: " msg)
@@ -48,11 +49,6 @@

#define ptr_to_u64(ptr)	((__u64)(unsigned long)(ptr))

#define min(a, b)							\
	({ typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _b : _a; })
#define max(a, b)							\
	({ typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _b : _a; })

#define NEXT_ARG()	({ argc--; argv++; if (argc < 0) usage(); })
#define NEXT_ARGP()	({ (*argc)--; (*argv)++; if (*argc < 0) usage(); })
#define BAD_ARG()	({ err("what is '%s'?\n", *argv); -1; })
+36 −8
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@

#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -46,6 +47,7 @@
#include <bpf.h>

#include "main.h"
#include "disasm.h"

static const char * const prog_type_name[] = {
	[BPF_PROG_TYPE_UNSPEC]		= "unspec",
@@ -297,11 +299,39 @@ static int do_show(int argc, char **argv)
	return 0;
}

static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...)
{
	va_list args;

	va_start(args, fmt);
	vprintf(fmt, args);
	va_end(args);
}

static void dump_xlated(void *buf, unsigned int len, bool opcodes)
{
	struct bpf_insn *insn = buf;
	unsigned int i;

	for (i = 0; i < len / sizeof(*insn); i++) {
		printf("% 4d: ", i);
		print_bpf_insn(print_insn, NULL, insn + i, true);

		if (opcodes) {
			printf("       ");
			print_hex(insn + i, 8, " ");
			printf("\n");
		}

		if (insn[i].code == (BPF_LD | BPF_IMM | BPF_DW))
			i++;
	}
}

static int do_dump(int argc, char **argv)
{
	struct bpf_prog_info info = {};
	__u32 len = sizeof(info);
	bool can_disasm = false;
	unsigned int buf_size;
	char *filepath = NULL;
	bool opcodes = false;
@@ -315,7 +345,6 @@ static int do_dump(int argc, char **argv)
	if (is_prefix(*argv, "jited")) {
		member_len = &info.jited_prog_len;
		member_ptr = &info.jited_prog_insns;
		can_disasm = true;
	} else if (is_prefix(*argv, "xlated")) {
		member_len = &info.xlated_prog_len;
		member_ptr = &info.xlated_prog_insns;
@@ -346,10 +375,6 @@ static int do_dump(int argc, char **argv)
		NEXT_ARG();
	}

	if (!filepath && !can_disasm) {
		err("expected 'file' got %s\n", *argv);
		return -1;
	}
	if (argc) {
		usage();
		return -1;
@@ -409,7 +434,10 @@ static int do_dump(int argc, char **argv)
			goto err_free;
		}
	} else {
		if (member_len == &info.jited_prog_len)
			disasm_print_insn(buf, *member_len, opcodes);
		else
			dump_xlated(buf, *member_len, opcodes);
	}

	free(buf);
@@ -430,7 +458,7 @@ static int do_help(int argc, char **argv)
{
	fprintf(stderr,
		"Usage: %s %s show [PROG]\n"
		"       %s %s dump xlated PROG  file FILE\n"
		"       %s %s dump xlated PROG [file FILE] [opcodes]\n"
		"       %s %s dump jited  PROG [file FILE] [opcodes]\n"
		"       %s %s pin   PROG FILE\n"
		"       %s %s help\n"