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