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/types.h> 14ecb96f7fSYonghong Song #include <sys/stat.h> 15e55190f2SBjörn Töpel #include <linux/perf_event.h> 16ecb96f7fSYonghong Song 174fe66415SDaniel T. Lee #include <bpf/bpf.h> 187cf245a3SToke Høiland-Jørgensen #include <bpf/libbpf.h> 19ecb96f7fSYonghong Song #include "bpf_util.h" 20ecb96f7fSYonghong Song #include "perf-sys.h" 21ecb96f7fSYonghong Song #include "trace_helpers.h" 22ecb96f7fSYonghong Song 234fe66415SDaniel T. Lee static struct bpf_program *progs[2]; 244fe66415SDaniel T. Lee static struct bpf_link *links[2]; 254fe66415SDaniel T. Lee 26ecb96f7fSYonghong Song #define CHECK_PERROR_RET(condition) ({ \ 27ecb96f7fSYonghong Song int __ret = !!(condition); \ 28ecb96f7fSYonghong Song if (__ret) { \ 29ecb96f7fSYonghong Song printf("FAIL: %s:\n", __func__); \ 30ecb96f7fSYonghong Song perror(" "); \ 31ecb96f7fSYonghong Song return -1; \ 32ecb96f7fSYonghong Song } \ 33ecb96f7fSYonghong Song }) 34ecb96f7fSYonghong Song 35ecb96f7fSYonghong Song #define CHECK_AND_RET(condition) ({ \ 36ecb96f7fSYonghong Song int __ret = !!(condition); \ 37ecb96f7fSYonghong Song if (__ret) \ 38ecb96f7fSYonghong Song return -1; \ 39ecb96f7fSYonghong Song }) 40ecb96f7fSYonghong Song 41ecb96f7fSYonghong Song static __u64 ptr_to_u64(void *ptr) 42ecb96f7fSYonghong Song { 43ecb96f7fSYonghong Song return (__u64) (unsigned long) ptr; 44ecb96f7fSYonghong Song } 45ecb96f7fSYonghong Song 46ecb96f7fSYonghong Song #define PMU_TYPE_FILE "/sys/bus/event_source/devices/%s/type" 47ecb96f7fSYonghong Song static int bpf_find_probe_type(const char *event_type) 48ecb96f7fSYonghong Song { 49ecb96f7fSYonghong Song char buf[256]; 50ecb96f7fSYonghong Song int fd, ret; 51ecb96f7fSYonghong Song 52ecb96f7fSYonghong Song ret = snprintf(buf, sizeof(buf), PMU_TYPE_FILE, event_type); 53ecb96f7fSYonghong Song CHECK_PERROR_RET(ret < 0 || ret >= sizeof(buf)); 54ecb96f7fSYonghong Song 55ecb96f7fSYonghong Song fd = open(buf, O_RDONLY); 56ecb96f7fSYonghong Song CHECK_PERROR_RET(fd < 0); 57ecb96f7fSYonghong Song 58ecb96f7fSYonghong Song ret = read(fd, buf, sizeof(buf)); 59ecb96f7fSYonghong Song close(fd); 60ecb96f7fSYonghong Song CHECK_PERROR_RET(ret < 0 || ret >= sizeof(buf)); 61ecb96f7fSYonghong Song 62ecb96f7fSYonghong Song errno = 0; 63ecb96f7fSYonghong Song ret = (int)strtol(buf, NULL, 10); 64ecb96f7fSYonghong Song CHECK_PERROR_RET(errno); 65ecb96f7fSYonghong Song return ret; 66ecb96f7fSYonghong Song } 67ecb96f7fSYonghong Song 68ecb96f7fSYonghong Song #define PMU_RETPROBE_FILE "/sys/bus/event_source/devices/%s/format/retprobe" 69ecb96f7fSYonghong Song static int bpf_get_retprobe_bit(const char *event_type) 70ecb96f7fSYonghong Song { 71ecb96f7fSYonghong Song char buf[256]; 72ecb96f7fSYonghong Song int fd, ret; 73ecb96f7fSYonghong Song 74ecb96f7fSYonghong Song ret = snprintf(buf, sizeof(buf), PMU_RETPROBE_FILE, event_type); 75ecb96f7fSYonghong Song CHECK_PERROR_RET(ret < 0 || ret >= sizeof(buf)); 76ecb96f7fSYonghong Song 77ecb96f7fSYonghong Song fd = open(buf, O_RDONLY); 78ecb96f7fSYonghong Song CHECK_PERROR_RET(fd < 0); 79ecb96f7fSYonghong Song 80ecb96f7fSYonghong Song ret = read(fd, buf, sizeof(buf)); 81ecb96f7fSYonghong Song close(fd); 82ecb96f7fSYonghong Song CHECK_PERROR_RET(ret < 0 || ret >= sizeof(buf)); 83ecb96f7fSYonghong Song CHECK_PERROR_RET(strlen(buf) < strlen("config:")); 84ecb96f7fSYonghong Song 85ecb96f7fSYonghong Song errno = 0; 86ecb96f7fSYonghong Song ret = (int)strtol(buf + strlen("config:"), NULL, 10); 87ecb96f7fSYonghong Song CHECK_PERROR_RET(errno); 88ecb96f7fSYonghong Song return ret; 89ecb96f7fSYonghong Song } 90ecb96f7fSYonghong Song 914fe66415SDaniel T. Lee static int test_debug_fs_kprobe(int link_idx, const char *fn_name, 92ecb96f7fSYonghong Song __u32 expected_fd_type) 93ecb96f7fSYonghong Song { 94ecb96f7fSYonghong Song __u64 probe_offset, probe_addr; 95ecb96f7fSYonghong Song __u32 len, prog_id, fd_type; 964fe66415SDaniel T. Lee int err, event_fd; 97ecb96f7fSYonghong Song char buf[256]; 98ecb96f7fSYonghong Song 99ecb96f7fSYonghong Song len = sizeof(buf); 1004fe66415SDaniel T. Lee event_fd = bpf_link__fd(links[link_idx]); 1014fe66415SDaniel T. Lee err = bpf_task_fd_query(getpid(), event_fd, 0, buf, &len, 102ecb96f7fSYonghong Song &prog_id, &fd_type, &probe_offset, 103ecb96f7fSYonghong Song &probe_addr); 104ecb96f7fSYonghong Song if (err < 0) { 105ecb96f7fSYonghong Song printf("FAIL: %s, for event_fd idx %d, fn_name %s\n", 1064fe66415SDaniel T. Lee __func__, link_idx, fn_name); 107ecb96f7fSYonghong Song perror(" :"); 108ecb96f7fSYonghong Song return -1; 109ecb96f7fSYonghong Song } 110ecb96f7fSYonghong Song if (strcmp(buf, fn_name) != 0 || 111ecb96f7fSYonghong Song fd_type != expected_fd_type || 112ecb96f7fSYonghong Song probe_offset != 0x0 || probe_addr != 0x0) { 113ecb96f7fSYonghong Song printf("FAIL: bpf_trace_event_query(event_fd[%d]):\n", 1144fe66415SDaniel T. Lee link_idx); 115ecb96f7fSYonghong Song printf("buf: %s, fd_type: %u, probe_offset: 0x%llx," 116ecb96f7fSYonghong Song " probe_addr: 0x%llx\n", 117ecb96f7fSYonghong Song buf, fd_type, probe_offset, probe_addr); 118ecb96f7fSYonghong Song return -1; 119ecb96f7fSYonghong Song } 120ecb96f7fSYonghong Song return 0; 121ecb96f7fSYonghong Song } 122ecb96f7fSYonghong Song 123ecb96f7fSYonghong Song static int test_nondebug_fs_kuprobe_common(const char *event_type, 124ecb96f7fSYonghong Song const char *name, __u64 offset, __u64 addr, bool is_return, 125ecb96f7fSYonghong Song char *buf, __u32 *buf_len, __u32 *prog_id, __u32 *fd_type, 126ecb96f7fSYonghong Song __u64 *probe_offset, __u64 *probe_addr) 127ecb96f7fSYonghong Song { 128ecb96f7fSYonghong Song int is_return_bit = bpf_get_retprobe_bit(event_type); 129ecb96f7fSYonghong Song int type = bpf_find_probe_type(event_type); 130ecb96f7fSYonghong Song struct perf_event_attr attr = {}; 1314fe66415SDaniel T. Lee struct bpf_link *link; 1324fe66415SDaniel T. Lee int fd, err = -1; 133ecb96f7fSYonghong Song 134ecb96f7fSYonghong Song if (type < 0 || is_return_bit < 0) { 135ecb96f7fSYonghong Song printf("FAIL: %s incorrect type (%d) or is_return_bit (%d)\n", 136ecb96f7fSYonghong Song __func__, type, is_return_bit); 1374fe66415SDaniel T. Lee return err; 138ecb96f7fSYonghong Song } 139ecb96f7fSYonghong Song 140ecb96f7fSYonghong Song attr.sample_period = 1; 141ecb96f7fSYonghong Song attr.wakeup_events = 1; 142ecb96f7fSYonghong Song if (is_return) 143ecb96f7fSYonghong Song attr.config |= 1 << is_return_bit; 144ecb96f7fSYonghong Song 145ecb96f7fSYonghong Song if (name) { 146ecb96f7fSYonghong Song attr.config1 = ptr_to_u64((void *)name); 147ecb96f7fSYonghong Song attr.config2 = offset; 148ecb96f7fSYonghong Song } else { 149ecb96f7fSYonghong Song attr.config1 = 0; 150ecb96f7fSYonghong Song attr.config2 = addr; 151ecb96f7fSYonghong Song } 152ecb96f7fSYonghong Song attr.size = sizeof(attr); 153ecb96f7fSYonghong Song attr.type = type; 154ecb96f7fSYonghong Song 155ecb96f7fSYonghong Song fd = sys_perf_event_open(&attr, -1, 0, -1, 0); 1564fe66415SDaniel T. Lee link = bpf_program__attach_perf_event(progs[0], fd); 1574fe66415SDaniel T. Lee if (libbpf_get_error(link)) { 1584fe66415SDaniel T. Lee printf("ERROR: bpf_program__attach_perf_event failed\n"); 1594fe66415SDaniel T. Lee link = NULL; 1604fe66415SDaniel T. Lee close(fd); 1614fe66415SDaniel T. Lee goto cleanup; 1624fe66415SDaniel T. Lee } 163ecb96f7fSYonghong Song 164ecb96f7fSYonghong Song CHECK_PERROR_RET(bpf_task_fd_query(getpid(), fd, 0, buf, buf_len, 165ecb96f7fSYonghong Song prog_id, fd_type, probe_offset, probe_addr) < 0); 1664fe66415SDaniel T. Lee err = 0; 167ecb96f7fSYonghong Song 1684fe66415SDaniel T. Lee cleanup: 1694fe66415SDaniel T. Lee bpf_link__destroy(link); 1704fe66415SDaniel T. Lee return err; 171ecb96f7fSYonghong Song } 172ecb96f7fSYonghong Song 173ecb96f7fSYonghong Song static int test_nondebug_fs_probe(const char *event_type, const char *name, 174ecb96f7fSYonghong Song __u64 offset, __u64 addr, bool is_return, 175ecb96f7fSYonghong Song __u32 expected_fd_type, 176ecb96f7fSYonghong Song __u32 expected_ret_fd_type, 177ecb96f7fSYonghong Song char *buf, __u32 buf_len) 178ecb96f7fSYonghong Song { 179ecb96f7fSYonghong Song __u64 probe_offset, probe_addr; 180ecb96f7fSYonghong Song __u32 prog_id, fd_type; 181ecb96f7fSYonghong Song int err; 182ecb96f7fSYonghong Song 183ecb96f7fSYonghong Song err = test_nondebug_fs_kuprobe_common(event_type, name, 184ecb96f7fSYonghong Song offset, addr, is_return, 185ecb96f7fSYonghong Song buf, &buf_len, &prog_id, 186ecb96f7fSYonghong Song &fd_type, &probe_offset, 187ecb96f7fSYonghong Song &probe_addr); 188ecb96f7fSYonghong Song if (err < 0) { 189ecb96f7fSYonghong Song printf("FAIL: %s, " 190ecb96f7fSYonghong Song "for name %s, offset 0x%llx, addr 0x%llx, is_return %d\n", 191ecb96f7fSYonghong Song __func__, name ? name : "", offset, addr, is_return); 192ecb96f7fSYonghong Song perror(" :"); 193ecb96f7fSYonghong Song return -1; 194ecb96f7fSYonghong Song } 195ecb96f7fSYonghong Song if ((is_return && fd_type != expected_ret_fd_type) || 196ecb96f7fSYonghong Song (!is_return && fd_type != expected_fd_type)) { 197ecb96f7fSYonghong Song printf("FAIL: %s, incorrect fd_type %u\n", 198ecb96f7fSYonghong Song __func__, fd_type); 199ecb96f7fSYonghong Song return -1; 200ecb96f7fSYonghong Song } 201ecb96f7fSYonghong Song if (name) { 202ecb96f7fSYonghong Song if (strcmp(name, buf) != 0) { 203ecb96f7fSYonghong Song printf("FAIL: %s, incorrect buf %s\n", __func__, buf); 204ecb96f7fSYonghong Song return -1; 205ecb96f7fSYonghong Song } 206ecb96f7fSYonghong Song if (probe_offset != offset) { 207ecb96f7fSYonghong Song printf("FAIL: %s, incorrect probe_offset 0x%llx\n", 208ecb96f7fSYonghong Song __func__, probe_offset); 209ecb96f7fSYonghong Song return -1; 210ecb96f7fSYonghong Song } 211ecb96f7fSYonghong Song } else { 212ecb96f7fSYonghong Song if (buf_len != 0) { 213ecb96f7fSYonghong Song printf("FAIL: %s, incorrect buf %p\n", 214ecb96f7fSYonghong Song __func__, buf); 215ecb96f7fSYonghong Song return -1; 216ecb96f7fSYonghong Song } 217ecb96f7fSYonghong Song 218ecb96f7fSYonghong Song if (probe_addr != addr) { 219ecb96f7fSYonghong Song printf("FAIL: %s, incorrect probe_addr 0x%llx\n", 220ecb96f7fSYonghong Song __func__, probe_addr); 221ecb96f7fSYonghong Song return -1; 222ecb96f7fSYonghong Song } 223ecb96f7fSYonghong Song } 224ecb96f7fSYonghong Song return 0; 225ecb96f7fSYonghong Song } 226ecb96f7fSYonghong Song 227ecb96f7fSYonghong Song static int test_debug_fs_uprobe(char *binary_path, long offset, bool is_return) 228ecb96f7fSYonghong Song { 2294fe66415SDaniel T. Lee char buf[256], event_alias[sizeof("test_1234567890")]; 230ecb96f7fSYonghong Song const char *event_type = "uprobe"; 231ecb96f7fSYonghong Song struct perf_event_attr attr = {}; 232ecb96f7fSYonghong Song __u64 probe_offset, probe_addr; 233ecb96f7fSYonghong Song __u32 len, prog_id, fd_type; 2344fe66415SDaniel T. Lee int err = -1, res, kfd, efd; 2354fe66415SDaniel T. Lee struct bpf_link *link; 236ecb96f7fSYonghong Song ssize_t bytes; 237ecb96f7fSYonghong Song 238*27d7fdf0SRoss Zwisler snprintf(buf, sizeof(buf), "/sys/kernel/tracing/%s_events", 239ecb96f7fSYonghong Song event_type); 2404fe66415SDaniel T. Lee kfd = open(buf, O_WRONLY | O_TRUNC, 0); 241ecb96f7fSYonghong Song CHECK_PERROR_RET(kfd < 0); 242ecb96f7fSYonghong Song 243ecb96f7fSYonghong Song res = snprintf(event_alias, sizeof(event_alias), "test_%d", getpid()); 244ecb96f7fSYonghong Song CHECK_PERROR_RET(res < 0 || res >= sizeof(event_alias)); 245ecb96f7fSYonghong Song 246ecb96f7fSYonghong Song res = snprintf(buf, sizeof(buf), "%c:%ss/%s %s:0x%lx", 247ecb96f7fSYonghong Song is_return ? 'r' : 'p', event_type, event_alias, 248ecb96f7fSYonghong Song binary_path, offset); 249ecb96f7fSYonghong Song CHECK_PERROR_RET(res < 0 || res >= sizeof(buf)); 250ecb96f7fSYonghong Song CHECK_PERROR_RET(write(kfd, buf, strlen(buf)) < 0); 251ecb96f7fSYonghong Song 252ecb96f7fSYonghong Song close(kfd); 253ecb96f7fSYonghong Song kfd = -1; 254ecb96f7fSYonghong Song 255*27d7fdf0SRoss Zwisler snprintf(buf, sizeof(buf), "/sys/kernel/tracing/events/%ss/%s/id", 256ecb96f7fSYonghong Song event_type, event_alias); 257ecb96f7fSYonghong Song efd = open(buf, O_RDONLY, 0); 258ecb96f7fSYonghong Song CHECK_PERROR_RET(efd < 0); 259ecb96f7fSYonghong Song 260ecb96f7fSYonghong Song bytes = read(efd, buf, sizeof(buf)); 261ecb96f7fSYonghong Song CHECK_PERROR_RET(bytes <= 0 || bytes >= sizeof(buf)); 262ecb96f7fSYonghong Song close(efd); 263ecb96f7fSYonghong Song buf[bytes] = '\0'; 264ecb96f7fSYonghong Song 265ecb96f7fSYonghong Song attr.config = strtol(buf, NULL, 0); 266ecb96f7fSYonghong Song attr.type = PERF_TYPE_TRACEPOINT; 267ecb96f7fSYonghong Song attr.sample_period = 1; 268ecb96f7fSYonghong Song attr.wakeup_events = 1; 2694fe66415SDaniel T. Lee 270ecb96f7fSYonghong Song kfd = sys_perf_event_open(&attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC); 2714fe66415SDaniel T. Lee link = bpf_program__attach_perf_event(progs[0], kfd); 2724fe66415SDaniel T. Lee if (libbpf_get_error(link)) { 2734fe66415SDaniel T. Lee printf("ERROR: bpf_program__attach_perf_event failed\n"); 2744fe66415SDaniel T. Lee link = NULL; 2754fe66415SDaniel T. Lee close(kfd); 2764fe66415SDaniel T. Lee goto cleanup; 2774fe66415SDaniel T. Lee } 278ecb96f7fSYonghong Song 279ecb96f7fSYonghong Song len = sizeof(buf); 280ecb96f7fSYonghong Song err = bpf_task_fd_query(getpid(), kfd, 0, buf, &len, 281ecb96f7fSYonghong Song &prog_id, &fd_type, &probe_offset, 282ecb96f7fSYonghong Song &probe_addr); 283ecb96f7fSYonghong Song if (err < 0) { 284ecb96f7fSYonghong Song printf("FAIL: %s, binary_path %s\n", __func__, binary_path); 285ecb96f7fSYonghong Song perror(" :"); 286ecb96f7fSYonghong Song return -1; 287ecb96f7fSYonghong Song } 288ecb96f7fSYonghong Song if ((is_return && fd_type != BPF_FD_TYPE_URETPROBE) || 289ecb96f7fSYonghong Song (!is_return && fd_type != BPF_FD_TYPE_UPROBE)) { 290ecb96f7fSYonghong Song printf("FAIL: %s, incorrect fd_type %u\n", __func__, 291ecb96f7fSYonghong Song fd_type); 292ecb96f7fSYonghong Song return -1; 293ecb96f7fSYonghong Song } 294ecb96f7fSYonghong Song if (strcmp(binary_path, buf) != 0) { 295ecb96f7fSYonghong Song printf("FAIL: %s, incorrect buf %s\n", __func__, buf); 296ecb96f7fSYonghong Song return -1; 297ecb96f7fSYonghong Song } 298ecb96f7fSYonghong Song if (probe_offset != offset) { 299ecb96f7fSYonghong Song printf("FAIL: %s, incorrect probe_offset 0x%llx\n", __func__, 300ecb96f7fSYonghong Song probe_offset); 301ecb96f7fSYonghong Song return -1; 302ecb96f7fSYonghong Song } 3034fe66415SDaniel T. Lee err = 0; 304ecb96f7fSYonghong Song 3054fe66415SDaniel T. Lee cleanup: 3064fe66415SDaniel T. Lee bpf_link__destroy(link); 3074fe66415SDaniel T. Lee return err; 308ecb96f7fSYonghong Song } 309ecb96f7fSYonghong Song 310ecb96f7fSYonghong Song int main(int argc, char **argv) 311ecb96f7fSYonghong Song { 312ecb96f7fSYonghong Song extern char __executable_start; 313ecb96f7fSYonghong Song char filename[256], buf[256]; 314ecb96f7fSYonghong Song __u64 uprobe_file_offset; 3154fe66415SDaniel T. Lee struct bpf_program *prog; 3164fe66415SDaniel T. Lee struct bpf_object *obj; 3174fe66415SDaniel T. Lee int i = 0, err = -1; 318ecb96f7fSYonghong Song 319ecb96f7fSYonghong Song if (load_kallsyms()) { 320ecb96f7fSYonghong Song printf("failed to process /proc/kallsyms\n"); 3214fe66415SDaniel T. Lee return err; 322ecb96f7fSYonghong Song } 323ecb96f7fSYonghong Song 3244fe66415SDaniel T. Lee snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 3254fe66415SDaniel T. Lee obj = bpf_object__open_file(filename, NULL); 3264fe66415SDaniel T. Lee if (libbpf_get_error(obj)) { 3274fe66415SDaniel T. Lee fprintf(stderr, "ERROR: opening BPF object file failed\n"); 3284fe66415SDaniel T. Lee return err; 3294fe66415SDaniel T. Lee } 3304fe66415SDaniel T. Lee 3314fe66415SDaniel T. Lee /* load BPF program */ 3324fe66415SDaniel T. Lee if (bpf_object__load(obj)) { 3334fe66415SDaniel T. Lee fprintf(stderr, "ERROR: loading BPF object file failed\n"); 3344fe66415SDaniel T. Lee goto cleanup; 3354fe66415SDaniel T. Lee } 3364fe66415SDaniel T. Lee 3374fe66415SDaniel T. Lee bpf_object__for_each_program(prog, obj) { 3384fe66415SDaniel T. Lee progs[i] = prog; 3394fe66415SDaniel T. Lee links[i] = bpf_program__attach(progs[i]); 3404fe66415SDaniel T. Lee if (libbpf_get_error(links[i])) { 3414fe66415SDaniel T. Lee fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 3424fe66415SDaniel T. Lee links[i] = NULL; 3434fe66415SDaniel T. Lee goto cleanup; 3444fe66415SDaniel T. Lee } 3454fe66415SDaniel T. Lee i++; 346ecb96f7fSYonghong Song } 347ecb96f7fSYonghong Song 348ecb96f7fSYonghong Song /* test two functions in the corresponding *_kern.c file */ 349d2e614cbSDaniel T. Lee CHECK_AND_RET(test_debug_fs_kprobe(0, "blk_mq_start_request", 350ecb96f7fSYonghong Song BPF_FD_TYPE_KPROBE)); 351bc069da6SRong Tao CHECK_AND_RET(test_debug_fs_kprobe(1, "__blk_account_io_done", 352ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE)); 353ecb96f7fSYonghong Song 354ecb96f7fSYonghong Song /* test nondebug fs kprobe */ 355ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", "bpf_check", 0x0, 0x0, 356ecb96f7fSYonghong Song false, BPF_FD_TYPE_KPROBE, 357ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 358ecb96f7fSYonghong Song buf, sizeof(buf))); 359ecb96f7fSYonghong Song #ifdef __x86_64__ 360ecb96f7fSYonghong Song /* set a kprobe on "bpf_check + 0x5", which is x64 specific */ 361ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", "bpf_check", 0x5, 0x0, 362ecb96f7fSYonghong Song false, BPF_FD_TYPE_KPROBE, 363ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 364ecb96f7fSYonghong Song buf, sizeof(buf))); 365ecb96f7fSYonghong Song #endif 366ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", "bpf_check", 0x0, 0x0, 367ecb96f7fSYonghong Song true, BPF_FD_TYPE_KPROBE, 368ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 369ecb96f7fSYonghong Song buf, sizeof(buf))); 370ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", NULL, 0x0, 371ecb96f7fSYonghong Song ksym_get_addr("bpf_check"), false, 372ecb96f7fSYonghong Song BPF_FD_TYPE_KPROBE, 373ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 374ecb96f7fSYonghong Song buf, sizeof(buf))); 375ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", NULL, 0x0, 376ecb96f7fSYonghong Song ksym_get_addr("bpf_check"), false, 377ecb96f7fSYonghong Song BPF_FD_TYPE_KPROBE, 378ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 379ecb96f7fSYonghong Song NULL, 0)); 380ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", NULL, 0x0, 381ecb96f7fSYonghong Song ksym_get_addr("bpf_check"), true, 382ecb96f7fSYonghong Song BPF_FD_TYPE_KPROBE, 383ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 384ecb96f7fSYonghong Song buf, sizeof(buf))); 385ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("kprobe", NULL, 0x0, 386ecb96f7fSYonghong Song ksym_get_addr("bpf_check"), true, 387ecb96f7fSYonghong Song BPF_FD_TYPE_KPROBE, 388ecb96f7fSYonghong Song BPF_FD_TYPE_KRETPROBE, 389ecb96f7fSYonghong Song 0, 0)); 390ecb96f7fSYonghong Song 391ecb96f7fSYonghong Song /* test nondebug fs uprobe */ 392ecb96f7fSYonghong Song /* the calculation of uprobe file offset is based on gcc 7.3.1 on x64 393ecb96f7fSYonghong Song * and the default linker script, which defines __executable_start as 394ecb96f7fSYonghong Song * the start of the .text section. The calculation could be different 395ecb96f7fSYonghong Song * on different systems with different compilers. The right way is 396ecb96f7fSYonghong Song * to parse the ELF file. We took a shortcut here. 397ecb96f7fSYonghong Song */ 3980303ce17SHailong Liu uprobe_file_offset = (unsigned long)main - (unsigned long)&__executable_start; 399ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("uprobe", (char *)argv[0], 400ecb96f7fSYonghong Song uprobe_file_offset, 0x0, false, 401ecb96f7fSYonghong Song BPF_FD_TYPE_UPROBE, 402ecb96f7fSYonghong Song BPF_FD_TYPE_URETPROBE, 403ecb96f7fSYonghong Song buf, sizeof(buf))); 404ecb96f7fSYonghong Song CHECK_AND_RET(test_nondebug_fs_probe("uprobe", (char *)argv[0], 405ecb96f7fSYonghong Song uprobe_file_offset, 0x0, true, 406ecb96f7fSYonghong Song BPF_FD_TYPE_UPROBE, 407ecb96f7fSYonghong Song BPF_FD_TYPE_URETPROBE, 408ecb96f7fSYonghong Song buf, sizeof(buf))); 409ecb96f7fSYonghong Song 410ecb96f7fSYonghong Song /* test debug fs uprobe */ 411ecb96f7fSYonghong Song CHECK_AND_RET(test_debug_fs_uprobe((char *)argv[0], uprobe_file_offset, 412ecb96f7fSYonghong Song false)); 413ecb96f7fSYonghong Song CHECK_AND_RET(test_debug_fs_uprobe((char *)argv[0], uprobe_file_offset, 414ecb96f7fSYonghong Song true)); 4154fe66415SDaniel T. Lee err = 0; 416ecb96f7fSYonghong Song 4174fe66415SDaniel T. Lee cleanup: 4184fe66415SDaniel T. Lee for (i--; i >= 0; i--) 4194fe66415SDaniel T. Lee bpf_link__destroy(links[i]); 4204fe66415SDaniel T. Lee 4214fe66415SDaniel T. Lee bpf_object__close(obj); 4224fe66415SDaniel T. Lee return err; 423ecb96f7fSYonghong Song } 424