@@ -39,7 +39,7 @@ CFLAGS += -g $(OPT_FLAGS) -rdynamic \
-I$(CURDIR) -I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR) \
-I$(TOOLSINCDIR) -I$(APIDIR) -I$(OUTPUT)
LDFLAGS += $(SAN_LDFLAGS)
-LDLIBS += $(LIBELF_LIBS) -lz -lrt -lpthread
+LDLIBS += $(LIBELF_LIBS) -lz -lrt -lpthread -ldl
ifneq ($(LLVM),)
# Silence some warnings when compiled with clang
new file mode 100644
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024, Oracle and/or its affiliates. */
+
+#include <test_progs.h>
+
+#include <dlfcn.h>
+
+#include "../sdt.h"
+
+#include "test_urdt.skel.h"
+#include "test_urdt_shared.skel.h"
+
+static volatile __u64 bla = 0xFEDCBA9876543210ULL;
+
+static void subtest_basic_urdt(void)
+{
+ LIBBPF_OPTS(bpf_urdt_opts, opts);
+ struct test_urdt *skel;
+ struct test_urdt__bss *bss;
+ long x = 1;
+ int y = 42;
+ int err;
+ int i;
+
+ skel = test_urdt__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "skel_open"))
+ return;
+
+ bss = skel->bss;
+ bss->my_pid = getpid();
+
+ err = test_urdt__attach(skel);
+ if (!ASSERT_OK(err, "skel_attach"))
+ goto cleanup;
+
+ /* urdt0 won't be auto-attached */
+ opts.urdt_cookie = 0xcafedead;
+ opts.urdt_nargs = 0;
+ skel->links.urdt0 = bpf_program__attach_urdt(skel->progs.urdt0,
+ 0 /*self*/, "/proc/self/exe",
+ "dyn", "urdt0", &opts);
+ if (!ASSERT_OK_PTR(skel->links.urdt0, "urdt0_link"))
+ goto cleanup;
+
+ BPF_URDT_PROBE0("dyn", "urdt0");
+
+ ASSERT_EQ(bss->urdt0_called, 1, "urdt0_called");
+
+ ASSERT_EQ(bss->urdt0_cookie, 0xcafedead, "urdt0_cookie");
+ ASSERT_EQ(bss->urdt0_arg_cnt, 0, "urdt0_arg_cnt");
+ ASSERT_EQ(bss->urdt0_arg_ret, -ENOENT, "urdt0_arg_ret");
+
+ BPF_URDT_PROBE3("dyn", "urdt3", x, y, &bla);
+
+ ASSERT_EQ(bss->urdt3_called, 1, "urdt3_called");
+ /* ensure the other 3-arg URDT probe does not trigger */
+ ASSERT_EQ(bss->urdt3alt_called, 0, "urdt3alt_notcalled");
+ /* auto-attached urdt3 gets default zero cookie value */
+ ASSERT_EQ(bss->urdt3_cookie, 0, "urdt3_cookie");
+ ASSERT_EQ(bss->urdt3_arg_cnt, 3, "urdt3_arg_cnt");
+
+ ASSERT_EQ(bss->urdt3_arg1, 1, "urdt3_arg1");
+ ASSERT_EQ(bss->urdt3_arg2, 42, "urdt3_arg2");
+ ASSERT_EQ((long)bss->urdt3_arg3, (long)&bla, "urdt3_arg3");
+
+ /* now call alternative 3-arg function, and make sure dyn/urdt3
+ * does not trigger.
+ */
+ BPF_URDT_PROBE3("dyn", "urdt3alt", y, &bla, x);
+
+ ASSERT_EQ(bss->urdt3alt_called, 1, "urdt3alt_called");
+ ASSERT_EQ(bss->urdt3_called, 1, "urdt3_notcalled");
+
+ ASSERT_EQ(bss->urdt3alt_arg1, 42, "urdt3alt_arg1");
+ ASSERT_EQ((long)bss->urdt3alt_arg2, (long)&bla, "urdt3_arg3");
+ ASSERT_EQ(bss->urdt3alt_arg3, 1, "urdt3alt_arg3");
+
+ BPF_URDT_PROBE11("dyn", "urdt11", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+
+ ASSERT_EQ(bss->urdt11_called, 1, "urdt11_called");
+ ASSERT_EQ(bss->urdt3_called, 1, "urdt3_called");
+ for (i = 0; i < 11; i++)
+ ASSERT_EQ(bss->urdt11_args[i], i + 1, "urdt11_arg");
+
+cleanup:
+ test_urdt__destroy(skel);
+}
+
+#define LIBBPF_SO_PATH "./tools/build/libbpf/libbpf.so"
+
+/* verify shared object attach/firing works for libbpf.so */
+static void subtest_shared_urdt(void)
+{
+ LIBBPF_OPTS(bpf_urdt_opts, opts);
+ struct test_urdt_shared *skel;
+ void *dlh;
+ void (*probe0)(const char *provider, const char *probe);
+ void (*probe4)(const char *provider, const char *probe, long arg1, long arg2,
+ long arg3, long arg4);
+ struct test_urdt_shared__bss *bss;
+ long x = 1;
+ int y = 42;
+ int z = 3;
+ int err;
+
+ skel = test_urdt_shared__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "skel_open"))
+ return;
+ bss = skel->bss;
+ bss->my_pid = getpid();
+
+ err = test_urdt_shared__attach(skel);
+ if (!ASSERT_OK(err, "skel_attach"))
+ goto cleanup;
+
+ /* urdt0 won't be auto-attached */
+ opts.urdt_cookie = 0xcafedead;
+ opts.urdt_nargs = 0;
+ skel->links.urdt0 = bpf_program__attach_urdt(skel->progs.urdt0,
+ -1 /* all */,
+ LIBBPF_SO_PATH,
+ "dyn", "urdt0", &opts);
+ if (!ASSERT_OK_PTR(skel->links.urdt0, "urdt0_link"))
+ goto cleanup;
+
+ /* test_progs is statically linked with libbpf, so we need to dlopen/dlsym
+ * probe firing functions in the shared object we have attached to in order
+ * to trigger probe firing. If a program is dynamically linked to libbpf
+ * for probe firing, this won't be needed, but we want to make sure this
+ * mode of operation works as it will likely be the common case.
+ */
+ dlh = dlopen(LIBBPF_SO_PATH, RTLD_NOW);
+ if (!ASSERT_NEQ(dlh, NULL, "dlopen"))
+ goto cleanup;
+ probe0 = dlsym(dlh, "bpf_urdt__probe0");
+ if (!ASSERT_NEQ(probe0, NULL, "dlsym_probe0"))
+ goto cleanup;
+ probe4 = dlsym(dlh, "bpf_urdt__probe4");
+ if (!ASSERT_NEQ(probe4, NULL, "dlsym_probe4"))
+ goto cleanup;
+
+ probe0("dyn", "urdt0");
+
+ ASSERT_EQ(bss->urdt0_called, 1, "urdt0_called");
+
+ ASSERT_EQ(bss->urdt0_cookie, 0xcafedead, "urdt0_cookie");
+ ASSERT_EQ(bss->urdt0_arg_cnt, 0, "urdt0_arg_cnt");
+ ASSERT_EQ(bss->urdt0_arg_ret, -ENOENT, "urdt0_arg_ret");
+
+ probe4("dyn", "urdt4", (long)x, (long)y, (long)z, (long)&bla);
+
+ ASSERT_EQ(bss->urdt4_called, 1, "urdt4_called");
+ /* auto-attached urdt4 gets default zero cookie value */
+ ASSERT_EQ(bss->urdt4_cookie, 0, "urdt4_cookie");
+ ASSERT_EQ(bss->urdt4_arg_cnt, 4, "urdt4_arg_cnt");
+
+ ASSERT_EQ(bss->urdt4_arg1, 1, "urdt4_arg1");
+ ASSERT_EQ(bss->urdt4_arg2, 42, "urdt4_arg2");
+ ASSERT_EQ(bss->urdt4_arg3, 3, "urdt4_arg3");
+ ASSERT_EQ((long)bss->urdt4_arg4, (long)&bla, "urdt4_arg4");
+cleanup:
+ if (dlh)
+ dlclose(dlh);
+ test_urdt_shared__destroy(skel);
+}
+
+void test_urdt(void)
+{
+ if (test__start_subtest("basic"))
+ subtest_basic_urdt();
+ if (test__start_subtest("shared"))
+ subtest_shared_urdt();
+}
new file mode 100644
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024, Oracle and/or its affiliates. */
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/urdt.bpf.h>
+
+int my_pid;
+
+int urdt0_called;
+int urdt0_cookie;
+int urdt0_arg_cnt;
+int urdt0_arg_ret;
+
+SEC("urdt")
+int BPF_URDT(urdt0)
+{
+ long tmp;
+
+ if (my_pid != (bpf_get_current_pid_tgid() >> 32))
+ return 0;
+
+ __sync_fetch_and_add(&urdt0_called, 1);
+
+ urdt0_cookie = bpf_urdt_cookie(ctx);
+ urdt0_arg_cnt = bpf_urdt_arg_cnt(ctx);
+ /* should return -ENOENT for any arg_num */
+ urdt0_arg_ret = bpf_usdt_arg(ctx, bpf_get_prandom_u32(), &tmp);
+ return 0;
+}
+
+int urdt3_called;
+int urdt3_cookie;
+int urdt3_arg_cnt;
+long urdt3_arg1;
+int urdt3_arg2;
+__u64 *urdt3_arg3;
+
+SEC("urdt//proc/self/exe:3:dyn:urdt3")
+int BPF_URDT(urdt3, long x, int y, __u64 *bla)
+{
+ if (my_pid != (bpf_get_current_pid_tgid() >> 32))
+ return 0;
+
+ __sync_fetch_and_add(&urdt3_called, 1);
+
+ __sync_fetch_and_add(&urdt3_cookie, bpf_urdt_cookie(ctx));
+ __sync_fetch_and_add(&urdt3_arg_cnt, bpf_urdt_arg_cnt(ctx));
+
+ __sync_fetch_and_add(&urdt3_arg1, x);
+ __sync_fetch_and_add(&urdt3_arg2, y);
+ __sync_fetch_and_add(&urdt3_arg3, bla);
+
+ return 0;
+}
+
+int urdt3alt_called;
+int urdt3alt_cookie;
+int urdt3alt_arg1;
+__u64 *urdt3alt_arg2;
+long urdt3alt_arg3;
+
+SEC("urdt//proc/self/exe:3:dyn:urdt3alt")
+int BPF_URDT(urdt3alt, int y, __u64 *bla, long x)
+{
+ __sync_fetch_and_add(&urdt3alt_called, 1);
+
+ __sync_fetch_and_add(&urdt3alt_cookie, bpf_urdt_cookie(ctx));
+
+ __sync_fetch_and_add(&urdt3alt_arg1, y);
+ __sync_fetch_and_add(&urdt3alt_arg2, bla);
+ __sync_fetch_and_add(&urdt3alt_arg3, x);
+
+ return 0;
+}
+
+int urdt11_called;
+int urdt11_args[11];
+
+SEC("urdt//proc/self/exe:11:dyn:urdt11")
+int BPF_URDT(urdt11, int arg1, int arg2, int arg3, int arg4, int arg5,
+ int arg6, int arg7, int arg8, int arg9, int arg10, int arg11)
+{
+ __sync_fetch_and_add(&urdt11_called, 1);
+ __sync_fetch_and_add(&urdt11_args[0], arg1);
+ __sync_fetch_and_add(&urdt11_args[1], arg2);
+ __sync_fetch_and_add(&urdt11_args[2], arg3);
+ __sync_fetch_and_add(&urdt11_args[3], arg4);
+ __sync_fetch_and_add(&urdt11_args[4], arg5);
+ __sync_fetch_and_add(&urdt11_args[5], arg6);
+ __sync_fetch_and_add(&urdt11_args[6], arg7);
+ __sync_fetch_and_add(&urdt11_args[7], arg8);
+ __sync_fetch_and_add(&urdt11_args[8], arg9);
+ __sync_fetch_and_add(&urdt11_args[9], arg10);
+ __sync_fetch_and_add(&urdt11_args[10], arg11);
+
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
new file mode 100644
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024, Oracle and/or its affiliates. */
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/urdt.bpf.h>
+
+int my_pid;
+
+int urdt0_called;
+int urdt0_cookie;
+int urdt0_arg_cnt;
+int urdt0_arg_ret;
+
+SEC("urdt")
+int BPF_URDT(urdt0)
+{
+ long tmp;
+
+ if (my_pid != (bpf_get_current_pid_tgid() >> 32))
+ return 0;
+
+ __sync_fetch_and_add(&urdt0_called, 1);
+
+ urdt0_cookie = bpf_urdt_cookie(ctx);
+ urdt0_arg_cnt = bpf_urdt_arg_cnt(ctx);
+ /* should return -ENOENT for any arg_num */
+ urdt0_arg_ret = bpf_usdt_arg(ctx, bpf_get_prandom_u32(), &tmp);
+ return 0;
+}
+
+int urdt4_called;
+int urdt4_cookie;
+int urdt4_arg_cnt;
+long urdt4_arg1;
+int urdt4_arg2;
+int urdt4_arg3;
+__u64 *urdt4_arg4;
+
+SEC("urdt/./tools/build/libbpf/libbpf.so:4:dyn:urdt4")
+int BPF_URDT(urdt4, long x, int y, int z, __u64 *bla)
+{
+ if (my_pid != (bpf_get_current_pid_tgid() >> 32))
+ return 0;
+
+ __sync_fetch_and_add(&urdt4_called, 1);
+
+ __sync_fetch_and_add(&urdt4_cookie, bpf_urdt_cookie(ctx));
+ __sync_fetch_and_add(&urdt4_arg_cnt, bpf_urdt_arg_cnt(ctx));
+
+ __sync_fetch_and_add(&urdt4_arg1, x);
+ __sync_fetch_and_add(&urdt4_arg2, y);
+ __sync_fetch_and_add(&urdt4_arg3, z);
+ __sync_fetch_and_add(&urdt4_arg4, bla);
+
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
Add tests that verify operation of URDT probes for both the statically and dynamically-linked libbpf cases. Ensure probe attach and auto-attach succeed, and argument counts, cookies and argument values match expectations. Signed-off-by: Alan Maguire <alan.maguire@oracle.com> --- tools/testing/selftests/bpf/Makefile | 2 +- tools/testing/selftests/bpf/prog_tests/urdt.c | 173 ++++++++++++++++++ tools/testing/selftests/bpf/progs/test_urdt.c | 100 ++++++++++ .../selftests/bpf/progs/test_urdt_shared.c | 59 ++++++ 4 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/bpf/prog_tests/urdt.c create mode 100644 tools/testing/selftests/bpf/progs/test_urdt.c create mode 100644 tools/testing/selftests/bpf/progs/test_urdt_shared.c