1 // SPDX-License-Identifier: GPL-2.0 2 #include <test_progs.h> 3 #include "test_stacktrace_build_id.skel.h" 4 5 BPF_EMBED_OBJ(stacktrace_build_id, "test_stacktrace_build_id.o"); 6 7 void test_stacktrace_build_id(void) 8 { 9 10 int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd; 11 struct test_stacktrace_build_id *skel; 12 int err, stack_trace_len; 13 __u32 key, previous_key, val, duration = 0; 14 char buf[256]; 15 int i, j; 16 struct bpf_stack_build_id id_offs[PERF_MAX_STACK_DEPTH]; 17 int build_id_matches = 0; 18 int retry = 1; 19 20 retry: 21 skel = test_stacktrace_build_id__open_and_load(&stacktrace_build_id_embed); 22 if (CHECK(!skel, "skel_open_and_load", "skeleton open/load failed\n")) 23 return; 24 25 err = test_stacktrace_build_id__attach(skel); 26 if (CHECK(err, "attach_tp", "err %d\n", err)) 27 goto cleanup; 28 29 /* find map fds */ 30 control_map_fd = bpf_map__fd(skel->maps.control_map); 31 stackid_hmap_fd = bpf_map__fd(skel->maps.stackid_hmap); 32 stackmap_fd = bpf_map__fd(skel->maps.stackmap); 33 stack_amap_fd = bpf_map__fd(skel->maps.stack_amap); 34 35 if (CHECK_FAIL(system("dd if=/dev/urandom of=/dev/zero count=4 2> /dev/null"))) 36 goto cleanup; 37 if (CHECK_FAIL(system("./urandom_read"))) 38 goto cleanup; 39 /* disable stack trace collection */ 40 key = 0; 41 val = 1; 42 bpf_map_update_elem(control_map_fd, &key, &val, 0); 43 44 /* for every element in stackid_hmap, we can find a corresponding one 45 * in stackmap, and vise versa. 46 */ 47 err = compare_map_keys(stackid_hmap_fd, stackmap_fd); 48 if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap", 49 "err %d errno %d\n", err, errno)) 50 goto cleanup; 51 52 err = compare_map_keys(stackmap_fd, stackid_hmap_fd); 53 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap", 54 "err %d errno %d\n", err, errno)) 55 goto cleanup; 56 57 err = extract_build_id(buf, 256); 58 59 if (CHECK(err, "get build_id with readelf", 60 "err %d errno %d\n", err, errno)) 61 goto cleanup; 62 63 err = bpf_map_get_next_key(stackmap_fd, NULL, &key); 64 if (CHECK(err, "get_next_key from stackmap", 65 "err %d, errno %d\n", err, errno)) 66 goto cleanup; 67 68 do { 69 char build_id[64]; 70 71 err = bpf_map_lookup_elem(stackmap_fd, &key, id_offs); 72 if (CHECK(err, "lookup_elem from stackmap", 73 "err %d, errno %d\n", err, errno)) 74 goto cleanup; 75 for (i = 0; i < PERF_MAX_STACK_DEPTH; ++i) 76 if (id_offs[i].status == BPF_STACK_BUILD_ID_VALID && 77 id_offs[i].offset != 0) { 78 for (j = 0; j < 20; ++j) 79 sprintf(build_id + 2 * j, "%02x", 80 id_offs[i].build_id[j] & 0xff); 81 if (strstr(buf, build_id) != NULL) 82 build_id_matches = 1; 83 } 84 previous_key = key; 85 } while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0); 86 87 /* stack_map_get_build_id_offset() is racy and sometimes can return 88 * BPF_STACK_BUILD_ID_IP instead of BPF_STACK_BUILD_ID_VALID; 89 * try it one more time. 90 */ 91 if (build_id_matches < 1 && retry--) { 92 test_stacktrace_build_id__destroy(skel); 93 printf("%s:WARN:Didn't find expected build ID from the map, retrying\n", 94 __func__); 95 goto retry; 96 } 97 98 if (CHECK(build_id_matches < 1, "build id match", 99 "Didn't find expected build ID from the map\n")) 100 goto cleanup; 101 102 stack_trace_len = PERF_MAX_STACK_DEPTH * 103 sizeof(struct bpf_stack_build_id); 104 err = compare_stack_ips(stackmap_fd, stack_amap_fd, stack_trace_len); 105 CHECK(err, "compare_stack_ips stackmap vs. stack_amap", 106 "err %d errno %d\n", err, errno); 107 108 cleanup: 109 test_stacktrace_build_id__destroy(skel); 110 } 111