Changing uretprobe_regs_trigger to allow the test for both
uprobe and uretprobe and renaming it to uprobe_regs_equal.

We check that both uprobe and uretprobe probes (bpf programs)
see expected registers with few exceptions.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
 .../selftests/bpf/prog_tests/uprobe_syscall.c | 57 ++++++++++++++-----
 .../selftests/bpf/progs/uprobe_syscall.c      |  4 +-
 2 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c 
b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c
index b3518f48329c..f1c297a9bb03 100644
--- a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c
+++ b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c
@@ -18,15 +18,17 @@
 
 #pragma GCC diagnostic ignored "-Wattributes"
 
-__naked unsigned long uretprobe_regs_trigger(void)
+__attribute__((aligned(16)))
+__nocf_check __weak __naked unsigned long uprobe_regs_trigger(void)
 {
        asm volatile (
-               "movq $0xdeadbeef, %rax\n"
+               ".byte 0x0f, 0x1f, 0x44, 0x00, 0x00     \n"
+               "movq $0xdeadbeef, %rax                 \n"
                "ret\n"
        );
 }
 
-__naked void uretprobe_regs(struct pt_regs *before, struct pt_regs *after)
+__naked void uprobe_regs(struct pt_regs *before, struct pt_regs *after)
 {
        asm volatile (
                "movq %r15,   0(%rdi)\n"
@@ -47,15 +49,17 @@ __naked void uretprobe_regs(struct pt_regs *before, struct 
pt_regs *after)
                "movq   $0, 120(%rdi)\n" /* orig_rax */
                "movq   $0, 128(%rdi)\n" /* rip      */
                "movq   $0, 136(%rdi)\n" /* cs       */
+               "pushq %rax\n"
                "pushf\n"
                "pop %rax\n"
                "movq %rax, 144(%rdi)\n" /* eflags   */
+               "pop %rax\n"
                "movq %rsp, 152(%rdi)\n" /* rsp      */
                "movq   $0, 160(%rdi)\n" /* ss       */
 
                /* save 2nd argument */
                "pushq %rsi\n"
-               "call uretprobe_regs_trigger\n"
+               "call uprobe_regs_trigger\n"
 
                /* save  return value and load 2nd argument pointer to rax */
                "pushq %rax\n"
@@ -95,25 +99,37 @@ __naked void uretprobe_regs(struct pt_regs *before, struct 
pt_regs *after)
 );
 }
 
-static void test_uretprobe_regs_equal(void)
+static void test_uprobe_regs_equal(bool retprobe)
 {
+       LIBBPF_OPTS(bpf_uprobe_opts, opts,
+               .retprobe = retprobe,
+       );
        struct uprobe_syscall *skel = NULL;
        struct pt_regs before = {}, after = {};
        unsigned long *pb = (unsigned long *) &before;
        unsigned long *pa = (unsigned long *) &after;
        unsigned long *pp;
+       unsigned long offset;
        unsigned int i, cnt;
-       int err;
+
+       offset = get_uprobe_offset(&uprobe_regs_trigger);
+       if (!ASSERT_GE(offset, 0, "get_uprobe_offset"))
+               return;
 
        skel = uprobe_syscall__open_and_load();
        if (!ASSERT_OK_PTR(skel, "uprobe_syscall__open_and_load"))
                goto cleanup;
 
-       err = uprobe_syscall__attach(skel);
-       if (!ASSERT_OK(err, "uprobe_syscall__attach"))
+       skel->links.probe = bpf_program__attach_uprobe_opts(skel->progs.probe,
+                               0, "/proc/self/exe", offset, &opts);
+       if (!ASSERT_OK_PTR(skel->links.probe, 
"bpf_program__attach_uprobe_opts"))
                goto cleanup;
 
-       uretprobe_regs(&before, &after);
+       /* make sure uprobe gets optimized */
+       if (!retprobe)
+               uprobe_regs_trigger();
+
+       uprobe_regs(&before, &after);
 
        pp = (unsigned long *) &skel->bss->regs;
        cnt = sizeof(before)/sizeof(*pb);
@@ -122,7 +138,7 @@ static void test_uretprobe_regs_equal(void)
                unsigned int offset = i * sizeof(unsigned long);
 
                /*
-                * Check register before and after uretprobe_regs_trigger call
+                * Check register before and after uprobe_regs_trigger call
                 * that triggers the uretprobe.
                 */
                switch (offset) {
@@ -136,7 +152,7 @@ static void test_uretprobe_regs_equal(void)
 
                /*
                 * Check register seen from bpf program and register after
-                * uretprobe_regs_trigger call
+                * uprobe_regs_trigger call (with rax exception, check below).
                 */
                switch (offset) {
                /*
@@ -149,6 +165,15 @@ static void test_uretprobe_regs_equal(void)
                case offsetof(struct pt_regs, rsp):
                case offsetof(struct pt_regs, ss):
                        break;
+               /*
+                * uprobe does not see return value in rax, it needs to see the
+                * original (before) rax value
+                */
+               case offsetof(struct pt_regs, rax):
+                       if (!retprobe) {
+                               ASSERT_EQ(pp[i], pb[i], "uprobe rax prog-before 
value check");
+                               break;
+                       }
                default:
                        if (!ASSERT_EQ(pp[i], pa[i], "register prog-after value 
check"))
                                fprintf(stdout, "failed register offset %u\n", 
offset);
@@ -186,13 +211,13 @@ static void test_uretprobe_regs_change(void)
        unsigned long cnt = sizeof(before)/sizeof(*pb);
        unsigned int i, err, offset;
 
-       offset = get_uprobe_offset(uretprobe_regs_trigger);
+       offset = get_uprobe_offset(uprobe_regs_trigger);
 
        err = write_bpf_testmod_uprobe(offset);
        if (!ASSERT_OK(err, "register_uprobe"))
                return;
 
-       uretprobe_regs(&before, &after);
+       uprobe_regs(&before, &after);
 
        err = write_bpf_testmod_uprobe(0);
        if (!ASSERT_OK(err, "unregister_uprobe"))
@@ -347,7 +372,7 @@ static void test_uretprobe_shadow_stack(void)
        }
 
        /* Run all of the uretprobe tests. */
-       test_uretprobe_regs_equal();
+       test_uprobe_regs_equal(false);
        test_uretprobe_regs_change();
        test_uretprobe_syscall_call();
 
@@ -709,7 +734,7 @@ static void test_uprobe_sigill(void)
 static void __test_uprobe_syscall(void)
 {
        if (test__start_subtest("uretprobe_regs_equal"))
-               test_uretprobe_regs_equal();
+               test_uprobe_regs_equal(true);
        if (test__start_subtest("uretprobe_regs_change"))
                test_uretprobe_regs_change();
        if (test__start_subtest("uretprobe_syscall_call"))
@@ -728,6 +753,8 @@ static void __test_uprobe_syscall(void)
                test_uprobe_race();
        if (test__start_subtest("uprobe_sigill"))
                test_uprobe_sigill();
+       if (test__start_subtest("uprobe_regs_equal"))
+               test_uprobe_regs_equal(false);
 }
 #else
 static void __test_uprobe_syscall(void)
diff --git a/tools/testing/selftests/bpf/progs/uprobe_syscall.c 
b/tools/testing/selftests/bpf/progs/uprobe_syscall.c
index 8a4fa6c7ef59..e08c31669e5a 100644
--- a/tools/testing/selftests/bpf/progs/uprobe_syscall.c
+++ b/tools/testing/selftests/bpf/progs/uprobe_syscall.c
@@ -7,8 +7,8 @@ struct pt_regs regs;
 
 char _license[] SEC("license") = "GPL";
 
-SEC("uretprobe//proc/self/exe:uretprobe_regs_trigger")
-int uretprobe(struct pt_regs *ctx)
+SEC("uprobe")
+int probe(struct pt_regs *ctx)
 {
        __builtin_memcpy(&regs, ctx, sizeof(regs));
        return 0;
-- 
2.49.0


Reply via email to