1*ecb96f7fSYonghong Song // SPDX-License-Identifier: GPL-2.0 2*ecb96f7fSYonghong Song 3*ecb96f7fSYonghong Song #include <stdio.h> 4*ecb96f7fSYonghong Song #include <stdlib.h> 5*ecb96f7fSYonghong Song #include <signal.h> 6*ecb96f7fSYonghong Song #include <unistd.h> 7*ecb96f7fSYonghong Song #include <stdbool.h> 8*ecb96f7fSYonghong Song #include <string.h> 9*ecb96f7fSYonghong Song #include <stdint.h> 10*ecb96f7fSYonghong Song #include <fcntl.h> 11*ecb96f7fSYonghong Song #include <linux/bpf.h> 12*ecb96f7fSYonghong Song #include <sys/ioctl.h> 13*ecb96f7fSYonghong Song #include <sys/resource.h> 14*ecb96f7fSYonghong Song #include <sys/types.h> 15*ecb96f7fSYonghong Song #include <sys/stat.h> 16*ecb96f7fSYonghong Song 17*ecb96f7fSYonghong Song #include "libbpf.h" 18*ecb96f7fSYonghong Song #include "bpf_load.h" 19*ecb96f7fSYonghong Song #include "bpf_util.h" 20*ecb96f7fSYonghong Song #include "perf-sys.h" 21*ecb96f7fSYonghong Song #include "trace_helpers.h" 22*ecb96f7fSYonghong Song 23*ecb96f7fSYonghong Song #define CHECK_PERROR_RET(condition) ({ \ 24*ecb96f7fSYonghong Song int __ret = !!(condition); \ 25*ecb96f7fSYonghong Song if (__ret) { \ 26*ecb96f7fSYonghong Song printf("FAIL: %s:\n", __func__); \ 27*ecb96f7fSYonghong Song perror(" "); \ 28*ecb96f7fSYonghong Song return -1; \ 29*ecb96f7fSYonghong Song } \ 30*ecb96f7fSYonghong Song }) 31*ecb96f7fSYonghong Song 32*ecb96f7fSYonghong Song #define CHECK_AND_RET(condition) ({ \ 33*ecb96f7fSYonghong Song int __ret = !!(condition); \ 34*ecb96f7fSYonghong Song if (__ret) \ 35*ecb96f7fSYonghong Song return -1; \ 36*ecb96f7fSYonghong Song }) 37*ecb96f7fSYonghong Song 38*ecb96f7fSYonghong Song static __u64 ptr_to_u64(void *ptr) 39*ecb96f7fSYonghong Song { 40*ecb96f7fSYonghong Song return (__u64) (unsigned long) ptr; 41*ecb96f7fSYonghong Song } 42*ecb96f7fSYonghong Song 43*ecb96f7fSYonghong Song #define PMU_TYPE_FILE "/sys/bus/event_source/devices/%s/type" 44*ecb96f7fSYonghong Song static int bpf_find_probe_type(const char *event_type) 45*ecb96f7fSYonghong Song { 46*ecb96f7fSYonghong Song char buf[256]; 47*ecb96f7fSYonghong Song int fd, ret; 48*ecb96f7fSYonghong Song 49*ecb96f7fSYonghong Song ret = snprintf(buf, sizeof(buf), PMU_TYPE_FILE, event_type); 50*ecb96f7fSYonghong Song CHECK_PERROR_RET(ret < 0 || ret >= sizeof(buf)); 51*ecb96f7fSYonghong Song 52*ecb96f7fSYonghong Song fd = open(buf, O_RDONLY); 53*ecb96f7fSYonghong Song CHECK_PERROR_RET(fd < 0); 54*ecb96f7fSYonghong Song 55*ecb96f7fSYonghong Song ret = read(fd, buf, sizeof(buf)); 56*ecb96f7fSYonghong Song close(fd); 57*ecb96f7fSYonghong Song CHECK_PERROR_RET(ret < 0 || ret >= sizeof(buf)); 58*ecb96f7fSYonghong Song 59*ecb96f7fSYonghong Song errno = 0; 60*ecb96f7fSYonghong Song ret = (int)strtol(buf, NULL, 10); 61*ecb96f7fSYonghong Song CHECK_PERROR_RET(errno); 62*ecb96f7fSYonghong Song return ret; 63*ecb96f7fSYonghong Song } 64*ecb96f7fSYonghong Song 65*ecb96f7fSYonghong Song #define PMU_RETPROBE_FILE "/sys/bus/event_source/devices/%s/format/retprobe" 66*ecb96f7fSYonghong Song static int bpf_get_retprobe_bit(const char *event_type) 67*ecb96f7fSYonghong Song { 68*ecb96f7fSYonghong Song char buf[256]; 69*ecb96f7fSYonghong Song int fd, ret; 70*ecb96f7fSYonghong Song 71*ecb96f7fSYonghong Song ret = snprintf(buf, sizeof(buf), PMU_RETPROBE_FILE, event_type); 72*ecb96f7fSYonghong Song CHECK_PERROR_RET(ret < 0 || ret >= sizeof(buf)); 73*ecb96f7fSYonghong Song 74*ecb96f7fSYonghong Song fd = open(buf, O_RDONLY); 75*ecb96f7fSYonghong Song CHECK_PERROR_RET(fd < 0); 76*ecb96f7fSYonghong Song 77*ecb96f7fSYonghong Song ret = read(fd, buf, sizeof(buf)); 78*ecb96f7fSYonghong Song close(fd); 79*ecb96f7fSYonghong Song CHECK_PERROR_RET(ret < 0 || ret >= sizeof(buf)); 80*ecb96f7fSYonghong Song CHECK_PERROR_RET(strlen(buf) < strlen("config:")); 81*ecb96f7fSYonghong Song 82*ecb96f7fSYonghong Song errno = 0; 83*ecb96f7fSYonghong Song ret = (int)strtol(buf + strlen("config:"), NULL, 10); 84*ecb96f7fSYonghong Song CHECK_PERROR_RET(errno); 85*ecb96f7fSYonghong Song return ret; 86*ecb96f7fSYonghong Song } 87*ecb96f7fSYonghong Song 88*ecb96f7fSYonghong Song static int test_debug_fs_kprobe(int prog_fd_idx, const char *fn_name, 89*ecb96f7fSYonghong Song __u32 expected_fd_type) 90*ecb96f7fSYonghong Song { 91*ecb96f7fSYonghong Song __u64 probe_offset, probe_addr; 92*ecb96f7fSYonghong Song __u32 len, prog_id, fd_type; 93*ecb96f7fSYonghong Song char buf[256]; 94*ecb96f7fSYonghong Song int err; 95*ecb96f7fSYonghong Song 96*ecb96f7fSYonghong Song len = sizeof(buf); 97*ecb96f7fSYonghong Song err = bpf_task_fd_query(getpid(), event_fd[prog_fd_idx], 0, buf, &len, 98*ecb96f7fSYonghong Song &prog_id, &fd_type, &probe_offset, 99*ecb96f7fSYonghong Song &probe_addr); 100*ecb96f7fSYonghong Song if (err < 0) { 101*ecb96f7fSYonghong Song printf("FAIL: %s, for event_fd idx %d, fn_name %s\n", 102*ecb96f7fSYonghong Song __func__, prog_fd_idx, fn_name); 103*ecb96f7fSYonghong Song perror(" :"); 104*ecb96f7fSYonghong Song return -1; 105*ecb96f7fSYonghong Song } 106*ecb96f7fSYonghong Song if (strcmp(buf, fn_name) != 0 || 107*ecb96f7fSYonghong Song fd_type != expected_fd_type || 108*ecb96f7fSYonghong Song probe_offset != 0x0 || probe_addr != 0x0) { 109*ecb96f7fSYonghong Song printf("FAIL: bpf_trace_event_query(event_fd[%d]):\n", 110*ecb96f7fSYonghong Song prog_fd_idx); 111*ecb96f7fSYonghong Song printf("buf: %s, fd_type: %u, probe_offset: 0x%llx," 112*ecb96f7fSYonghong Song " probe_addr: 0x%llx\n", 113*ecb96f7fSYonghong Song buf, fd_type, probe_offset, probe_addr); 114*ecb96f7fSYonghong Song return -1; 115*ecb96f7fSYonghong Song } 116*ecb96f7fSYonghong Song return 0; 117*ecb96f7fSYonghong Song } 118*ecb96f7fSYonghong Song 119*ecb96f7fSYonghong Song static int test_nondebug_fs_kuprobe_common(const char *event_type, 120*ecb96f7fSYonghong Song const char *name, __u64 offset, __u64 addr, bool is_return, 121*ecb96f7fSYonghong Song char *buf, __u32 *buf_len, __u32 *prog_id, __u32 *fd_type, 122*ecb96f7fSYonghong Song __u64 *probe_offset, __u64 *probe_addr) 123*ecb96f7fSYonghong Song { 124*ecb96f7fSYonghong Song int is_return_bit = bpf_get_retprobe_bit(event_type); 125*ecb96f7fSYonghong Song int type = bpf_find_probe_type(event_type); 126*ecb96f7fSYonghong Song struct perf_event_attr attr = {}; 127*ecb96f7fSYonghong Song int fd; 128*ecb96f7fSYonghong Song 129*ecb96f7fSYonghong Song if (type < 0 || is_return_bit < 0) { 130*ecb96f7fSYonghong Song printf("FAIL: %s incorrect type (%d) or is_return_bit (%d)\n", 131*ecb96f7fSYonghong Song __func__, type, is_return_bit); 132*ecb96f7fSYonghong Song return -1; 133*ecb96f7fSYonghong Song } 134*ecb96f7fSYonghong Song 135*ecb96f7fSYonghong Song attr.sample_period = 1; 136*ecb96f7fSYonghong Song attr.wakeup_events = 1; 137*ecb96f7fSYonghong Song if (is_return) 138*ecb96f7fSYonghong Song attr.config |= 1 << is_return_bit; 139*ecb96f7fSYonghong Song 140*ecb96f7fSYonghong Song if (name) { 141*ecb96f7fSYonghong Song attr.config1 = ptr_to_u64((void *)name); 142*ecb96f7fSYonghong Song attr.config2 = offset; 143*ecb96f7fSYonghong Song } else { 144*ecb96f7fSYonghong Song attr.config1 = 0; 145*ecb96f7fSYonghong Song attr.config2 = addr; 146*ecb96f7fSYonghong Song } 147*ecb96f7fSYonghong Song attr.size = sizeof(attr); 148*ecb96f7fSYonghong Song attr.type = type; 149*ecb96f7fSYonghong Song 150*ecb96f7fSYonghong Song fd = sys_perf_event_open(&attr, -1, 0, -1, 0); 151*ecb96f7fSYonghong Song CHECK_PERROR_RET(fd < 0); 152*ecb96f7fSYonghong Song 153*ecb96f7fSYonghong Song CHECK_PERROR_RET(ioctl(fd, PERF_EVENT_IOC_ENABLE, 0) < 0); 154*ecb96f7fSYonghong Song CHECK_PERROR_RET(ioctl(fd, PERF_EVENT_IOC_SET_BPF, prog_fd[0]) < 0); 155*ecb96f7fSYonghong Song CHECK_PERROR_RET(bpf_task_fd_query(getpid(), fd, 0, buf, buf_len, 156*ecb96f7fSYonghong Song prog_id, fd_type, probe_offset, probe_addr) < 0); 157*ecb96f7fSYonghong Song 158*ecb96f7fSYonghong Song return 0; 159*ecb96f7fSYonghong Song } 160*ecb96f7fSYonghong Song 161*ecb96f7fSYonghong Song static int test_nondebug_fs_probe(const char *event_type, const char *name, 162*ecb96f7fSYonghong Song __u64 offset, __u64 addr, bool is_return, 163*ecb96f7fSYonghong Song __u32 expected_fd_type, 164*ecb96f7fSYonghong Song __u32 expected_ret_fd_type, 165*ecb96f7fSYonghong Song char *buf, __u32 buf_len) 166*ecb96f7fSYonghong Song { 167*ecb96f7fSYonghong Song __u64 probe_offset, probe_addr; 168*ecb96f7fSYonghong Song __u32 prog_id, fd_type; 169*ecb96f7fSYonghong Song int err; 170*ecb96f7fSYonghong Song 171*ecb96f7fSYonghong Song err = test_nondebug_fs_kuprobe_common(event_type, name, 172*ecb96f7fSYonghong Song offset, addr, is_return, 173*ecb96f7fSYonghong Song buf, &buf_len, &prog_id, 174*ecb96f7fSYonghong Song &fd_type, &probe_offset, 175*ecb96f7fSYonghong Song &probe_addr); 176*ecb96f7fSYonghong Song if (err < 0) { 177*ecb96f7fSYonghong Song printf("FAIL: %s, " 178*ecb96f7fSYonghong Song "for name %s, offset 0x%llx, addr 0x%llx, is_return %d\n", 179*ecb96f7fSYonghong Song __func__, name ? name : "", offset, addr, is_return); 180*ecb96f7fSYonghong Song perror(" :"); 181*ecb96f7fSYonghong Song return -1; 182*ecb96f7fSYonghong Song } 183*ecb96f7fSYonghong Song if ((is_return && fd_type != expected_ret_fd_type) || 184*ecb96f7fSYonghong Song (!is_return && fd_type != expected_fd_type)) { 185*ecb96f7fSYonghong Song printf("FAIL: %s, incorrect fd_type %u\n", 186*ecb96f7fSYonghong Song __func__, fd_type); 187*ecb96f7fSYonghong Song return -1; 188*ecb96f7fSYonghong Song } 189*ecb96f7fSYonghong Song if (name) { 190*ecb96f7fSYonghong Song if (strcmp(name, buf) != 0) { 191*ecb96f7fSYonghong Song printf("FAIL: %s, incorrect buf %s\n", __func__, buf); 192*ecb96f7fSYonghong Song return -1; 193*ecb96f7fSYonghong Song } 194*ecb96f7fSYonghong Song if (probe_offset != offset) { 195*ecb96f7fSYonghong Song printf("FAIL: %s, incorrect probe_offset 0x%llx\n", 196*ecb96f7fSYonghong Song __func__, probe_offset); 197*ecb96f7fSYonghong Song return -1; 198*ecb96f7fSYonghong Song } 199*ecb96f7fSYonghong Song } else { 200*ecb96f7fSYonghong Song if (buf_len != 0) { 201*ecb96f7fSYonghong Song printf("FAIL: %s, incorrect buf %p\n", 202*ecb96f7fSYonghong Song __func__, buf); 203*ecb96f7fSYonghong Song return -1; 204*ecb96f7fSYonghong Song } 205*ecb96f7fSYonghong Song 206*ecb96f7fSYonghong Song if (probe_addr != addr) { 207*ecb96f7fSYonghong Song printf("FAIL: %s, incorrect probe_addr 0x%llx\n", 208*ecb96f7fSYonghong Song __func__, probe_addr); 209*ecb96f7fSYonghong Song return -1; 210*ecb96f7fSYonghong Song } 211*ecb96f7fSYonghong Song } 212*ecb96f7fSYonghong Song return 0; 213*ecb96f7fSYonghong Song } 214*ecb96f7fSYonghong Song 215*ecb96f7fSYonghong Song static int test_debug_fs_uprobe(char *binary_path, long offset, bool is_return) 216*ecb96f7fSYonghong Song { 217*ecb96f7fSYonghong Song const char *event_type = "uprobe"; 218*ecb96f7fSYonghong Song struct perf_event_attr attr = {}; 219*ecb96f7fSYonghong Song char buf[256], event_alias[256]; 220*ecb96f7fSYonghong Song __u64 probe_offset, probe_addr; 221*ecb96f7fSYonghong Song __u32 len, prog_id, fd_type; 222*ecb96f7fSYonghong Song int err, res, kfd, efd; 223*ecb96f7fSYonghong Song ssize_t bytes; 224*ecb96f7fSYonghong Song 225*ecb96f7fSYonghong Song snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/%s_events", 226*ecb96f7fSYonghong Song event_type); 227*ecb96f7fSYonghong Song kfd = open(buf, O_WRONLY | O_APPEND, 0); 228*ecb96f7fSYonghong Song CHECK_PERROR_RET(kfd < 0); 229*ecb96f7fSYonghong Song 230*ecb96f7fSYonghong Song res = snprintf(event_alias, sizeof(event_alias), "test_%d", getpid()); 231*ecb96f7fSYonghong Song CHECK_PERROR_RET(res < 0 || res >= sizeof(event_alias)); 232*ecb96f7fSYonghong Song 233*ecb96f7fSYonghong Song res = snprintf(buf, sizeof(buf), "%c:%ss/%s %s:0x%lx", 234*ecb96f7fSYonghong Song is_return ? 'r' : 'p', event_type, event_alias, 235*ecb96f7fSYonghong Song binary_path, offset); 236*ecb96f7fSYonghong Song CHECK_PERROR_RET(res < 0 || res >= sizeof(buf)); 237*ecb96f7fSYonghong Song CHECK_PERROR_RET(write(kfd, buf, strlen(buf)) < 0); 238*ecb96f7fSYonghong Song 239*ecb96f7fSYonghong Song close(kfd); 240*ecb96f7fSYonghong Song kfd = -1; 241*ecb96f7fSYonghong Song 242*ecb96f7fSYonghong Song snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%ss/%s/id", 243*ecb96f7fSYonghong Song event_type, event_alias); 244*ecb96f7fSYonghong Song efd = open(buf, O_RDONLY, 0); 245*ecb96f7fSYonghong Song CHECK_PERROR_RET(efd < 0); 246*ecb96f7fSYonghong Song 247*ecb96f7fSYonghong Song bytes = read(efd, buf, sizeof(buf)); 248*ecb96f7fSYonghong Song CHECK_PERROR_RET(bytes <= 0 || bytes >= sizeof(buf)); 249*ecb96f7fSYonghong Song close(efd); 250*ecb96f7fSYonghong Song buf[bytes] = '\0'; 251*ecb96f7fSYonghong Song 252*ecb96f7fSYonghong Song attr.config = strtol(buf, NULL, 0); 253*ecb96f7fSYonghong Song attr.type = PERF_TYPE_TRACEPOINT; 254*ecb96f7fSYonghong Song attr.sample_period = 1; 255*ecb96f7fSYonghong Song attr.wakeup_events = 1; 256*ecb96f7fSYonghong Song kfd = sys_perf_event_open(&attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC); 257*ecb96f7fSYonghong Song CHECK_PERROR_RET(kfd < 0); 258*ecb96f7fSYonghong Song CHECK_PERROR_RET(ioctl(kfd, PERF_EVENT_IOC_SET_BPF, prog_fd[0]) < 0); 259*ecb96f7fSYonghong Song CHECK_PERROR_RET(ioctl(kfd, PERF_EVENT_IOC_ENABLE, 0) < 0); 260*ecb96f7fSYonghong Song 261*ecb96f7fSYonghong Song len = sizeof(buf); 262*ecb96f7fSYonghong Song err = bpf_task_fd_query(getpid(), kfd, 0, buf, &len, 263*ecb96f7fSYonghong Song &prog_id, &fd_type, &probe_offset, 264*ecb96f7fSYonghong Song &probe_addr); 265*ecb96f7fSYonghong Song if (err < 0) { 266*ecb96f7fSYonghong Song printf("FAIL: %s, binary_path %s\n", __func__, binary_path); 267*ecb96f7fSYonghong Song perror(" :"); 268*ecb96f7fSYonghong Song return -1; 269*ecb96f7fSYonghong Song } 270*ecb96f7fSYonghong Song if ((is_return && fd_type != BPF_FD_TYPE_URETPROBE) || 271*ecb96f7fSYonghong Song (!is_return && fd_type != BPF_FD_TYPE_UPROBE)) { 272*ecb96f7fSYonghong Song printf("FAIL: %s, incorrect fd_type %u\n", __func__, 273*ecb96f7fSYonghong Song fd_type); 274*ecb96f7fSYonghong Song return -1; 275*ecb96f7fSYonghong Song } 276*ecb96f7fSYonghong Song if (strcmp(binary_path, buf) != 0) { 277*ecb96f7fSYonghong Song printf("FAIL: %s, incorrect buf %s\n", __func__, buf); 278*ecb96f7fSYonghong Song return -1; 279*ecb96f7fSYonghong Song } 280*ecb96f7fSYonghong Song if (probe_offset != offset) { 281*ecb96f7fSYonghong Song printf("FAIL: %s, incorrect probe_offset 0x%llx\n", __func__, 282*ecb96f7fSYonghong Song probe_offset); 283*ecb96f7fSYonghong Song return -1; 284*ecb96f7fSYonghong Song } 285*ecb96f7fSYonghong Song 286*ecb96f7fSYonghong Song close(kfd); 287*ecb96f7fSYonghong Song return 0; 288*ecb96f7fSYonghong Song } 289*ecb96f7fSYonghong Song 290*ecb96f7fSYonghong Song int main(int argc, char **argv) 291*ecb96f7fSYonghong Song { 292*ecb96f7fSYonghong Song struct rlimit r = {1024*1024, RLIM_INFINITY}; 293*ecb96f7fSYonghong Song extern char __executable_start; 294*ecb96f7fSYonghong Song char filename[256], buf[256]; 295*ecb96f7fSYonghong Song __u64 uprobe_file_offset; 296*ecb96f7fSYonghong Song 297*ecb96f7fSYonghong Song snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 298*ecb96f7fSYonghong Song if (setrlimit(RLIMIT_MEMLOCK, &r)) { 299*ecb96f7fSYonghong Song perror("setrlimit(RLIMIT_MEMLOCK)"); 300*ecb96f7fSYonghong Song return 1; 301*ecb96f7fSYonghong Song } 302*ecb96f7fSYonghong Song 303*ecb96f7fSYonghong Song if (load_kallsyms()) { 304*ecb96f7fSYonghong Song printf("failed to process /proc/kallsyms\n"); 305*ecb96f7fSYonghong Song return 1; 306*ecb96f7fSYonghong Song } 307*ecb96f7fSYonghong Song 308*ecb96f7fSYonghong Song if (load_bpf_file(filename)) { 309*ecb96f7fSYonghong Song printf("%s", bpf_log_buf); 310*ecb96f7fSYonghong Song return 1; 311*ecb96f7fSYonghong Song } 312*ecb96f7fSYonghong Song 313*ecb96f7fSYonghong Song /* test two functions in the corresponding *_kern.c file */ 314*ecb96f7fSYonghong Song CHECK_AND_RET(test_debug_fs_kprobe(0, "blk_start_request", 315*ecb96f7fSYonghong Song BPF_FD_TYPE_KPROBE)); 316*ecb96f7fSYonghong Song CHECK_AND_RET(test_debug_fs_kprobe(1, "blk_account_io_completion", 317*ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE)); 318*ecb96f7fSYonghong Song 319*ecb96f7fSYonghong Song /* test nondebug fs kprobe */ 320*ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", "bpf_check", 0x0, 0x0, 321*ecb96f7fSYonghong Song false, BPF_FD_TYPE_KPROBE, 322*ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 323*ecb96f7fSYonghong Song buf, sizeof(buf))); 324*ecb96f7fSYonghong Song #ifdef __x86_64__ 325*ecb96f7fSYonghong Song /* set a kprobe on "bpf_check + 0x5", which is x64 specific */ 326*ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", "bpf_check", 0x5, 0x0, 327*ecb96f7fSYonghong Song false, BPF_FD_TYPE_KPROBE, 328*ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 329*ecb96f7fSYonghong Song buf, sizeof(buf))); 330*ecb96f7fSYonghong Song #endif 331*ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", "bpf_check", 0x0, 0x0, 332*ecb96f7fSYonghong Song true, BPF_FD_TYPE_KPROBE, 333*ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 334*ecb96f7fSYonghong Song buf, sizeof(buf))); 335*ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", NULL, 0x0, 336*ecb96f7fSYonghong Song ksym_get_addr("bpf_check"), false, 337*ecb96f7fSYonghong Song BPF_FD_TYPE_KPROBE, 338*ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 339*ecb96f7fSYonghong Song buf, sizeof(buf))); 340*ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", NULL, 0x0, 341*ecb96f7fSYonghong Song ksym_get_addr("bpf_check"), false, 342*ecb96f7fSYonghong Song BPF_FD_TYPE_KPROBE, 343*ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 344*ecb96f7fSYonghong Song NULL, 0)); 345*ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", NULL, 0x0, 346*ecb96f7fSYonghong Song ksym_get_addr("bpf_check"), true, 347*ecb96f7fSYonghong Song BPF_FD_TYPE_KPROBE, 348*ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 349*ecb96f7fSYonghong Song buf, sizeof(buf))); 350*ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", NULL, 0x0, 351*ecb96f7fSYonghong Song ksym_get_addr("bpf_check"), true, 352*ecb96f7fSYonghong Song BPF_FD_TYPE_KPROBE, 353*ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 354*ecb96f7fSYonghong Song 0, 0)); 355*ecb96f7fSYonghong Song 356*ecb96f7fSYonghong Song /* test nondebug fs uprobe */ 357*ecb96f7fSYonghong Song /* the calculation of uprobe file offset is based on gcc 7.3.1 on x64 358*ecb96f7fSYonghong Song * and the default linker script, which defines __executable_start as 359*ecb96f7fSYonghong Song * the start of the .text section. The calculation could be different 360*ecb96f7fSYonghong Song * on different systems with different compilers. The right way is 361*ecb96f7fSYonghong Song * to parse the ELF file. We took a shortcut here. 362*ecb96f7fSYonghong Song */ 363*ecb96f7fSYonghong Song uprobe_file_offset = (__u64)main - (__u64)&__executable_start; 364*ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("uprobe", (char *)argv[0], 365*ecb96f7fSYonghong Song uprobe_file_offset, 0x0, false, 366*ecb96f7fSYonghong Song BPF_FD_TYPE_UPROBE, 367*ecb96f7fSYonghong Song BPF_FD_TYPE_URETPROBE, 368*ecb96f7fSYonghong Song buf, sizeof(buf))); 369*ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("uprobe", (char *)argv[0], 370*ecb96f7fSYonghong Song uprobe_file_offset, 0x0, true, 371*ecb96f7fSYonghong Song BPF_FD_TYPE_UPROBE, 372*ecb96f7fSYonghong Song BPF_FD_TYPE_URETPROBE, 373*ecb96f7fSYonghong Song buf, sizeof(buf))); 374*ecb96f7fSYonghong Song 375*ecb96f7fSYonghong Song /* test debug fs uprobe */ 376*ecb96f7fSYonghong Song CHECK_AND_RET(test_debug_fs_uprobe((char *)argv[0], uprobe_file_offset, 377*ecb96f7fSYonghong Song false)); 378*ecb96f7fSYonghong Song CHECK_AND_RET(test_debug_fs_uprobe((char *)argv[0], uprobe_file_offset, 379*ecb96f7fSYonghong Song true)); 380*ecb96f7fSYonghong Song 381*ecb96f7fSYonghong Song return 0; 382*ecb96f7fSYonghong Song } 383