linux/tools/testing/selftests/bpf/prog_tests/attach_probe.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <test_progs.h>
   3#include "test_attach_probe.skel.h"
   4
   5#if defined(__powerpc64__) && defined(_CALL_ELF) && _CALL_ELF == 2
   6
   7#define OP_RT_RA_MASK   0xffff0000UL
   8#define LIS_R2          0x3c400000UL
   9#define ADDIS_R2_R12    0x3c4c0000UL
  10#define ADDI_R2_R2      0x38420000UL
  11
  12static ssize_t get_offset(ssize_t addr, ssize_t base)
  13{
  14        u32 *insn = (u32 *) addr;
  15
  16        /*
  17         * A PPC64 ABIv2 function may have a local and a global entry
  18         * point. We need to use the local entry point when patching
  19         * functions, so identify and step over the global entry point
  20         * sequence.
  21         *
  22         * The global entry point sequence is always of the form:
  23         *
  24         * addis r2,r12,XXXX
  25         * addi  r2,r2,XXXX
  26         *
  27         * A linker optimisation may convert the addis to lis:
  28         *
  29         * lis   r2,XXXX
  30         * addi  r2,r2,XXXX
  31         */
  32        if ((((*insn & OP_RT_RA_MASK) == ADDIS_R2_R12) ||
  33             ((*insn & OP_RT_RA_MASK) == LIS_R2)) &&
  34            ((*(insn + 1) & OP_RT_RA_MASK) == ADDI_R2_R2))
  35                return (ssize_t)(insn + 2) - base;
  36        else
  37                return addr - base;
  38}
  39#else
  40#define get_offset(addr, base) (addr - base)
  41#endif
  42
  43ssize_t get_base_addr() {
  44        size_t start, offset;
  45        char buf[256];
  46        FILE *f;
  47
  48        f = fopen("/proc/self/maps", "r");
  49        if (!f)
  50                return -errno;
  51
  52        while (fscanf(f, "%zx-%*x %s %zx %*[^\n]\n",
  53                      &start, buf, &offset) == 3) {
  54                if (strcmp(buf, "r-xp") == 0) {
  55                        fclose(f);
  56                        return start - offset;
  57                }
  58        }
  59
  60        fclose(f);
  61        return -EINVAL;
  62}
  63
  64void test_attach_probe(void)
  65{
  66        int duration = 0;
  67        struct bpf_link *kprobe_link, *kretprobe_link;
  68        struct bpf_link *uprobe_link, *uretprobe_link;
  69        struct test_attach_probe* skel;
  70        size_t uprobe_offset;
  71        ssize_t base_addr;
  72
  73        base_addr = get_base_addr();
  74        if (CHECK(base_addr < 0, "get_base_addr",
  75                  "failed to find base addr: %zd", base_addr))
  76                return;
  77        uprobe_offset = get_offset((size_t)&get_base_addr, base_addr);
  78
  79        skel = test_attach_probe__open_and_load();
  80        if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
  81                return;
  82        if (CHECK(!skel->bss, "check_bss", ".bss wasn't mmap()-ed\n"))
  83                goto cleanup;
  84
  85        kprobe_link = bpf_program__attach_kprobe(skel->progs.handle_kprobe,
  86                                                 false /* retprobe */,
  87                                                 SYS_NANOSLEEP_KPROBE_NAME);
  88        if (!ASSERT_OK_PTR(kprobe_link, "attach_kprobe"))
  89                goto cleanup;
  90        skel->links.handle_kprobe = kprobe_link;
  91
  92        kretprobe_link = bpf_program__attach_kprobe(skel->progs.handle_kretprobe,
  93                                                    true /* retprobe */,
  94                                                    SYS_NANOSLEEP_KPROBE_NAME);
  95        if (!ASSERT_OK_PTR(kretprobe_link, "attach_kretprobe"))
  96                goto cleanup;
  97        skel->links.handle_kretprobe = kretprobe_link;
  98
  99        uprobe_link = bpf_program__attach_uprobe(skel->progs.handle_uprobe,
 100                                                 false /* retprobe */,
 101                                                 0 /* self pid */,
 102                                                 "/proc/self/exe",
 103                                                 uprobe_offset);
 104        if (!ASSERT_OK_PTR(uprobe_link, "attach_uprobe"))
 105                goto cleanup;
 106        skel->links.handle_uprobe = uprobe_link;
 107
 108        uretprobe_link = bpf_program__attach_uprobe(skel->progs.handle_uretprobe,
 109                                                    true /* retprobe */,
 110                                                    -1 /* any pid */,
 111                                                    "/proc/self/exe",
 112                                                    uprobe_offset);
 113        if (!ASSERT_OK_PTR(uretprobe_link, "attach_uretprobe"))
 114                goto cleanup;
 115        skel->links.handle_uretprobe = uretprobe_link;
 116
 117        /* trigger & validate kprobe && kretprobe */
 118        usleep(1);
 119
 120        if (CHECK(skel->bss->kprobe_res != 1, "check_kprobe_res",
 121                  "wrong kprobe res: %d\n", skel->bss->kprobe_res))
 122                goto cleanup;
 123        if (CHECK(skel->bss->kretprobe_res != 2, "check_kretprobe_res",
 124                  "wrong kretprobe res: %d\n", skel->bss->kretprobe_res))
 125                goto cleanup;
 126
 127        /* trigger & validate uprobe & uretprobe */
 128        get_base_addr();
 129
 130        if (CHECK(skel->bss->uprobe_res != 3, "check_uprobe_res",
 131                  "wrong uprobe res: %d\n", skel->bss->uprobe_res))
 132                goto cleanup;
 133        if (CHECK(skel->bss->uretprobe_res != 4, "check_uretprobe_res",
 134                  "wrong uretprobe res: %d\n", skel->bss->uretprobe_res))
 135                goto cleanup;
 136
 137cleanup:
 138        test_attach_probe__destroy(skel);
 139}
 140