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