Re: [PATCH bpf-next v2 0/5] bpftool: Add inline annotations when dumping program CFGs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2023-03-27 at 12:06 +0100, Quentin Monnet wrote:
> This set contains some improvements for bpftool's "visual" program dump
> option, which produces the control flow graph in a DOT format. The main
> objective is to add support for inline annotations on such graphs, so that
> we can have the C source code for the program showing up alongside the
> instructions, when available. The last commits also make it possible to
> display the line numbers or the bare opcodes in the graph, as supported by
> regular program dumps.
> 
> v2: Replace fputc(..., stdout) with putchar(...) in dotlabel_puts().

Hi Quentin,

It looks like currently there are no test cases for bpftool prog dump.
Borrowing an idea to mix bpf program with comments parsed by awk from
prog_tests/btf_dump.c it is possible to put together something like
below (although, would be much simpler as a bash script). Is it worth
the effort or dump format is too unstable?

Thanks,
Eduard

---

diff --git a/tools/testing/selftests/bpf/prog_tests/bpftool_cfg.c b/tools/testing/selftests/bpf/prog_tests/bpftool_cfg.c
new file mode 100644
index 000000000000..f582a93b5ee9
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/bpftool_cfg.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <test_progs.h>
+
+#include "bpf/libbpf.h"
+#include "bpftool_cfg.skel.h"
+
+static int system_to_tmp(char *tmp_template, char *cmd)
+{
+	char buf[1024];
+	int fd, err;
+
+	fd = mkstemp(tmp_template);
+	if (!ASSERT_GE(fd, 0, "mkstemp"))
+		return fd;
+
+	snprintf(buf, sizeof(buf), "%s > %s", cmd, tmp_template);
+	err = system(buf);
+	if (err) {
+		PRINT_FAIL("Command %s failed: err %d\n", cmd, err);
+		remove(tmp_template);
+		return err;
+	}
+
+	return 0;
+}
+
+void test_bpftool_cfg(void)
+{
+	const char *prog_pin_path = "/sys/fs/bpf/bpftool_cfg_test_pin";
+	const char *bpftool = "./tools/build/bpftool/bpftool";
+	char bpftool_tmp[256] = "/tmp/bpftool_test_cfg.XXXXXX";
+	char awk_tmp[256] = "/tmp/bpftool_test_awk.XXXXXX";
+	struct bpftool_cfg *skel;
+	const char *test_file;
+	char cmd_buf[1024];
+	FILE *cmd;
+	int err;
+
+	skel = bpftool_cfg__open_and_load();
+	if (!skel) {
+		PRINT_FAIL("failed to load bpftool_cfg program: %d (%s)\n",
+			   errno, strerror(errno));
+		return;
+	}
+
+	err = bpf_program__pin(skel->progs.bpftool_cfg_nanosleep, prog_pin_path);
+	if (err) {
+		PRINT_FAIL("failed to pin bpftool_cfg program: err %d, errno = %d (%s)\n",
+			   err, errno, strerror(errno));
+		goto out;
+	}
+
+	/* When the test is run with O=, kselftest copies TEST_FILES
+	 * without preserving the directory structure.
+	 */
+	if (access("progs/bpftool_cfg.c", R_OK) == 0)
+		test_file = "progs/bpftool_cfg.c";
+	else if (access("bpftool_cfg.c", R_OK) == 0)
+		test_file = "bpftool_cfg.c";
+	else {
+		PRINT_FAIL("Can't find bpftool_cfg.c\n");
+		goto out_unpin;
+	}
+
+	cmd = fmemopen(cmd_buf, sizeof(cmd_buf), "w");
+	fprintf(cmd, "awk '");
+	fprintf(cmd, "    /END-BPFTOOL-CFG/   { out=0 } ");
+	fprintf(cmd, "    out                 { print $0 } ");
+	fprintf(cmd, "    /START-BPFTOOL-CFG/ { out=1 } ");
+	fprintf(cmd, "' '%s' > '%s'", test_file, awk_tmp);
+	fclose(cmd);
+	err = system_to_tmp(awk_tmp, cmd_buf);
+	if (!ASSERT_OK(err, "awk"))
+		goto out_unpin;
+
+	cmd = fmemopen(cmd_buf, sizeof(cmd_buf), "w");
+	fprintf(cmd, "%s prog dump xlated pinned %s visual", bpftool, prog_pin_path);
+	fclose(cmd);
+	err = system_to_tmp(bpftool_tmp, cmd_buf);
+	if (!ASSERT_OK(err, "bpftool"))
+		goto out_delete;
+
+	cmd = fmemopen(cmd_buf, sizeof(cmd_buf), "w");
+	fprintf(cmd, "diff -u %s %s", awk_tmp, bpftool_tmp);
+	fclose(cmd);
+	err = system(cmd_buf);
+	if (!ASSERT_OK(err, "diff"))
+		goto out_delete;
+
+out_delete:
+	if (awk_tmp[0])
+		remove(awk_tmp);
+	if (bpftool_tmp[0])
+		remove(bpftool_tmp);
+out_unpin:
+	bpf_program__unpin(skel->progs.bpftool_cfg_nanosleep, prog_pin_path);
+out:
+	bpftool_cfg__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/bpftool_cfg.c b/tools/testing/selftests/bpf/progs/bpftool_cfg.c
new file mode 100644
index 000000000000..d10c4e2cecbd
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/bpftool_cfg.c
@@ -0,0 +1,36 @@
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+#include "bpf_misc.h"
+
+/*
+START-BPFTOOL-CFG
+digraph "DOT graph for eBPF program" {
+subgraph "cluster_0" {
+	style="dashed";
+	color="black";
+	label="func_0 ()";
+	fn_0_bb_0 [shape=Mdiamond,style=filled,label="ENTRY"];
+
+	fn_0_bb_2 [shape=record,style=filled,label="{\
+; int bpftool_cfg_nanosleep(void * ctx):\l\
+; return 0;\l\
+0: (b4) w0 = 0\l\
+ | 1: (95) exit\l\
+}"];
+
+	fn_0_bb_1 [shape=Mdiamond,style=filled,label="EXIT"];
+
+	fn_0_bb_0:s -> fn_0_bb_2:n [style="solid,bold", color=black, weight=10, constraint=true];
+	fn_0_bb_2:s -> fn_0_bb_1:n [style="solid,bold", color=black, weight=10, constraint=true];
+	fn_0_bb_0:s -> fn_0_bb_1:n [style="invis", constraint=true];
+}
+}
+END-BPFTOOL-CFG
+*/
+
+SEC("tp/syscalls/sys_enter_getpid")
+int bpftool_cfg_nanosleep(void *ctx)
+{
+	return 0;
+}




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux