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