0001
0002
0003 #include <test_progs.h>
0004
0005 #define _SDT_HAS_SEMAPHORES 1
0006 #include "../sdt.h"
0007
0008 #include "test_usdt.skel.h"
0009 #include "test_urandom_usdt.skel.h"
0010
0011 int lets_test_this(int);
0012
0013 static volatile int idx = 2;
0014 static volatile __u64 bla = 0xFEDCBA9876543210ULL;
0015 static volatile short nums[] = {-1, -2, -3, -4};
0016
0017 static volatile struct {
0018 int x;
0019 signed char y;
0020 } t1 = { 1, -127 };
0021
0022 #define SEC(name) __attribute__((section(name), used))
0023
0024 unsigned short test_usdt0_semaphore SEC(".probes");
0025 unsigned short test_usdt3_semaphore SEC(".probes");
0026 unsigned short test_usdt12_semaphore SEC(".probes");
0027
0028 static void __always_inline trigger_func(int x) {
0029 long y = 42;
0030
0031 if (test_usdt0_semaphore)
0032 STAP_PROBE(test, usdt0);
0033 if (test_usdt3_semaphore)
0034 STAP_PROBE3(test, usdt3, x, y, &bla);
0035 if (test_usdt12_semaphore) {
0036 STAP_PROBE12(test, usdt12,
0037 x, x + 1, y, x + y, 5,
0038 y / 7, bla, &bla, -9, nums[x],
0039 nums[idx], t1.y);
0040 }
0041 }
0042
0043 static void subtest_basic_usdt(void)
0044 {
0045 LIBBPF_OPTS(bpf_usdt_opts, opts);
0046 struct test_usdt *skel;
0047 struct test_usdt__bss *bss;
0048 int err;
0049
0050 skel = test_usdt__open_and_load();
0051 if (!ASSERT_OK_PTR(skel, "skel_open"))
0052 return;
0053
0054 bss = skel->bss;
0055 bss->my_pid = getpid();
0056
0057 err = test_usdt__attach(skel);
0058 if (!ASSERT_OK(err, "skel_attach"))
0059 goto cleanup;
0060
0061
0062 opts.usdt_cookie = 0xcafedeadbeeffeed;
0063 skel->links.usdt0 = bpf_program__attach_usdt(skel->progs.usdt0,
0064 0 , "/proc/self/exe",
0065 "test", "usdt0", &opts);
0066 if (!ASSERT_OK_PTR(skel->links.usdt0, "usdt0_link"))
0067 goto cleanup;
0068
0069 trigger_func(1);
0070
0071 ASSERT_EQ(bss->usdt0_called, 1, "usdt0_called");
0072 ASSERT_EQ(bss->usdt3_called, 1, "usdt3_called");
0073 ASSERT_EQ(bss->usdt12_called, 1, "usdt12_called");
0074
0075 ASSERT_EQ(bss->usdt0_cookie, 0xcafedeadbeeffeed, "usdt0_cookie");
0076 ASSERT_EQ(bss->usdt0_arg_cnt, 0, "usdt0_arg_cnt");
0077 ASSERT_EQ(bss->usdt0_arg_ret, -ENOENT, "usdt0_arg_ret");
0078
0079
0080 ASSERT_EQ(bss->usdt3_cookie, 0, "usdt3_cookie");
0081 ASSERT_EQ(bss->usdt3_arg_cnt, 3, "usdt3_arg_cnt");
0082
0083 ASSERT_EQ(bss->usdt3_arg_rets[0], 0, "usdt3_arg1_ret");
0084 ASSERT_EQ(bss->usdt3_arg_rets[1], 0, "usdt3_arg2_ret");
0085 ASSERT_EQ(bss->usdt3_arg_rets[2], 0, "usdt3_arg3_ret");
0086 ASSERT_EQ(bss->usdt3_args[0], 1, "usdt3_arg1");
0087 ASSERT_EQ(bss->usdt3_args[1], 42, "usdt3_arg2");
0088 ASSERT_EQ(bss->usdt3_args[2], (uintptr_t)&bla, "usdt3_arg3");
0089
0090
0091 ASSERT_EQ(bss->usdt12_cookie, 0, "usdt12_cookie");
0092 ASSERT_EQ(bss->usdt12_arg_cnt, 12, "usdt12_arg_cnt");
0093
0094 ASSERT_EQ(bss->usdt12_args[0], 1, "usdt12_arg1");
0095 ASSERT_EQ(bss->usdt12_args[1], 1 + 1, "usdt12_arg2");
0096 ASSERT_EQ(bss->usdt12_args[2], 42, "usdt12_arg3");
0097 ASSERT_EQ(bss->usdt12_args[3], 42 + 1, "usdt12_arg4");
0098 ASSERT_EQ(bss->usdt12_args[4], 5, "usdt12_arg5");
0099 ASSERT_EQ(bss->usdt12_args[5], 42 / 7, "usdt12_arg6");
0100 ASSERT_EQ(bss->usdt12_args[6], bla, "usdt12_arg7");
0101 ASSERT_EQ(bss->usdt12_args[7], (uintptr_t)&bla, "usdt12_arg8");
0102 ASSERT_EQ(bss->usdt12_args[8], -9, "usdt12_arg9");
0103 ASSERT_EQ(bss->usdt12_args[9], nums[1], "usdt12_arg10");
0104 ASSERT_EQ(bss->usdt12_args[10], nums[idx], "usdt12_arg11");
0105 ASSERT_EQ(bss->usdt12_args[11], t1.y, "usdt12_arg12");
0106
0107
0108
0109
0110
0111
0112
0113 trigger_func(2);
0114
0115 ASSERT_EQ(bss->usdt0_called, 2, "usdt0_called");
0116 ASSERT_EQ(bss->usdt3_called, 2, "usdt3_called");
0117 ASSERT_EQ(bss->usdt12_called, 2, "usdt12_called");
0118
0119
0120 ASSERT_EQ(bss->usdt3_args[0], 2, "usdt3_arg1");
0121
0122 ASSERT_EQ(bss->usdt12_args[0], 2, "usdt12_arg1");
0123 ASSERT_EQ(bss->usdt12_args[1], 2 + 1, "usdt12_arg2");
0124 ASSERT_EQ(bss->usdt12_args[3], 42 + 2, "usdt12_arg4");
0125 ASSERT_EQ(bss->usdt12_args[9], nums[2], "usdt12_arg10");
0126
0127
0128 bpf_link__destroy(skel->links.usdt3);
0129
0130 opts.usdt_cookie = 0xBADC00C51E;
0131 skel->links.usdt3 = bpf_program__attach_usdt(skel->progs.usdt3, -1 ,
0132 "/proc/self/exe", "test", "usdt3", &opts);
0133 if (!ASSERT_OK_PTR(skel->links.usdt3, "usdt3_reattach"))
0134 goto cleanup;
0135
0136 trigger_func(3);
0137
0138 ASSERT_EQ(bss->usdt3_called, 3, "usdt3_called");
0139
0140 ASSERT_EQ(bss->usdt3_cookie, 0xBADC00C51E, "usdt3_cookie");
0141 ASSERT_EQ(bss->usdt3_arg_cnt, 3, "usdt3_arg_cnt");
0142
0143 ASSERT_EQ(bss->usdt3_arg_rets[0], 0, "usdt3_arg1_ret");
0144 ASSERT_EQ(bss->usdt3_arg_rets[1], 0, "usdt3_arg2_ret");
0145 ASSERT_EQ(bss->usdt3_arg_rets[2], 0, "usdt3_arg3_ret");
0146 ASSERT_EQ(bss->usdt3_args[0], 3, "usdt3_arg1");
0147 ASSERT_EQ(bss->usdt3_args[1], 42, "usdt3_arg2");
0148 ASSERT_EQ(bss->usdt3_args[2], (uintptr_t)&bla, "usdt3_arg3");
0149
0150 cleanup:
0151 test_usdt__destroy(skel);
0152 }
0153
0154 unsigned short test_usdt_100_semaphore SEC(".probes");
0155 unsigned short test_usdt_300_semaphore SEC(".probes");
0156 unsigned short test_usdt_400_semaphore SEC(".probes");
0157
0158 #define R10(F, X) F(X+0); F(X+1);F(X+2); F(X+3); F(X+4); \
0159 F(X+5); F(X+6); F(X+7); F(X+8); F(X+9);
0160 #define R100(F, X) R10(F,X+ 0);R10(F,X+10);R10(F,X+20);R10(F,X+30);R10(F,X+40); \
0161 R10(F,X+50);R10(F,X+60);R10(F,X+70);R10(F,X+80);R10(F,X+90);
0162
0163
0164 static void __always_inline f100(int x)
0165 {
0166 STAP_PROBE1(test, usdt_100, x);
0167 }
0168
0169 __weak void trigger_100_usdts(void)
0170 {
0171 R100(f100, 0);
0172 }
0173
0174
0175
0176
0177
0178
0179 static void __always_inline f300(int x)
0180 {
0181 STAP_PROBE1(test, usdt_300, x);
0182 }
0183
0184 __weak void trigger_300_usdts(void)
0185 {
0186 R100(f300, 0);
0187 R100(f300, 100);
0188 R100(f300, 200);
0189 }
0190
0191 static void __always_inline f400(int x __attribute__((unused)))
0192 {
0193 STAP_PROBE1(test, usdt_400, 400);
0194 }
0195
0196
0197
0198
0199
0200
0201 __weak void trigger_400_usdts(void)
0202 {
0203 R100(f400, 0);
0204 R100(f400, 100);
0205 R100(f400, 200);
0206 R100(f400, 300);
0207 }
0208
0209 static void subtest_multispec_usdt(void)
0210 {
0211 LIBBPF_OPTS(bpf_usdt_opts, opts);
0212 struct test_usdt *skel;
0213 struct test_usdt__bss *bss;
0214 int err, i;
0215
0216 skel = test_usdt__open_and_load();
0217 if (!ASSERT_OK_PTR(skel, "skel_open"))
0218 return;
0219
0220 bss = skel->bss;
0221 bss->my_pid = getpid();
0222
0223 err = test_usdt__attach(skel);
0224 if (!ASSERT_OK(err, "skel_attach"))
0225 goto cleanup;
0226
0227
0228
0229
0230
0231 trigger_100_usdts();
0232
0233 ASSERT_EQ(bss->usdt_100_called, 100, "usdt_100_called");
0234 ASSERT_EQ(bss->usdt_100_sum, 99 * 100 / 2, "usdt_100_sum");
0235
0236
0237
0238
0239
0240
0241 for (i = 0; i < 2; i++) {
0242 bpf_link__destroy(skel->links.usdt_100);
0243
0244 skel->links.usdt_100 = bpf_program__attach_usdt(skel->progs.usdt_100, -1,
0245 "/proc/self/exe",
0246 "test", "usdt_100", NULL);
0247 if (!ASSERT_OK_PTR(skel->links.usdt_100, "usdt_100_reattach"))
0248 goto cleanup;
0249
0250 bss->usdt_100_sum = 0;
0251 trigger_100_usdts();
0252
0253 ASSERT_EQ(bss->usdt_100_called, (i + 1) * 100 + 100, "usdt_100_called");
0254 ASSERT_EQ(bss->usdt_100_sum, 99 * 100 / 2, "usdt_100_sum");
0255 }
0256
0257
0258
0259
0260
0261
0262 trigger_300_usdts();
0263
0264
0265 bpf_link__destroy(skel->links.usdt_100);
0266 skel->links.usdt_100 = bpf_program__attach_usdt(skel->progs.usdt_100, -1, "/proc/self/exe",
0267 "test", "usdt_300", NULL);
0268 err = -errno;
0269 if (!ASSERT_ERR_PTR(skel->links.usdt_100, "usdt_300_bad_attach"))
0270 goto cleanup;
0271 ASSERT_EQ(err, -E2BIG, "usdt_300_attach_err");
0272
0273
0274
0275
0276 bss->usdt_100_called = 0;
0277 bss->usdt_100_sum = 0;
0278
0279 f300(777);
0280
0281 ASSERT_EQ(bss->usdt_100_called, 0, "usdt_301_called");
0282 ASSERT_EQ(bss->usdt_100_sum, 0, "usdt_301_sum");
0283
0284
0285
0286
0287
0288
0289
0290
0291 skel->links.usdt_100 = bpf_program__attach_usdt(skel->progs.usdt_100, -1,
0292 "/proc/self/exe",
0293 "test", "usdt_400", NULL);
0294 if (!ASSERT_OK_PTR(skel->links.usdt_100, "usdt_400_attach"))
0295 goto cleanup;
0296
0297 trigger_400_usdts();
0298
0299 ASSERT_EQ(bss->usdt_100_called, 400, "usdt_400_called");
0300 ASSERT_EQ(bss->usdt_100_sum, 400 * 400, "usdt_400_sum");
0301
0302 cleanup:
0303 test_usdt__destroy(skel);
0304 }
0305
0306 static FILE *urand_spawn(int *pid)
0307 {
0308 FILE *f;
0309
0310
0311 f = popen("./urandom_read 1 report-pid", "r");
0312 if (!f)
0313 return NULL;
0314
0315 if (fscanf(f, "%d", pid) != 1) {
0316 pclose(f);
0317 return NULL;
0318 }
0319
0320 return f;
0321 }
0322
0323 static int urand_trigger(FILE **urand_pipe)
0324 {
0325 int exit_code;
0326
0327
0328 exit_code = pclose(*urand_pipe);
0329 *urand_pipe = NULL;
0330
0331 return exit_code;
0332 }
0333
0334 static void subtest_urandom_usdt(bool auto_attach)
0335 {
0336 struct test_urandom_usdt *skel;
0337 struct test_urandom_usdt__bss *bss;
0338 struct bpf_link *l;
0339 FILE *urand_pipe = NULL;
0340 int err, urand_pid = 0;
0341
0342 skel = test_urandom_usdt__open_and_load();
0343 if (!ASSERT_OK_PTR(skel, "skel_open"))
0344 return;
0345
0346 urand_pipe = urand_spawn(&urand_pid);
0347 if (!ASSERT_OK_PTR(urand_pipe, "urand_spawn"))
0348 goto cleanup;
0349
0350 bss = skel->bss;
0351 bss->urand_pid = urand_pid;
0352
0353 if (auto_attach) {
0354 err = test_urandom_usdt__attach(skel);
0355 if (!ASSERT_OK(err, "skel_auto_attach"))
0356 goto cleanup;
0357 } else {
0358 l = bpf_program__attach_usdt(skel->progs.urand_read_without_sema,
0359 urand_pid, "./urandom_read",
0360 "urand", "read_without_sema", NULL);
0361 if (!ASSERT_OK_PTR(l, "urand_without_sema_attach"))
0362 goto cleanup;
0363 skel->links.urand_read_without_sema = l;
0364
0365 l = bpf_program__attach_usdt(skel->progs.urand_read_with_sema,
0366 urand_pid, "./urandom_read",
0367 "urand", "read_with_sema", NULL);
0368 if (!ASSERT_OK_PTR(l, "urand_with_sema_attach"))
0369 goto cleanup;
0370 skel->links.urand_read_with_sema = l;
0371
0372 l = bpf_program__attach_usdt(skel->progs.urandlib_read_without_sema,
0373 urand_pid, "./liburandom_read.so",
0374 "urandlib", "read_without_sema", NULL);
0375 if (!ASSERT_OK_PTR(l, "urandlib_without_sema_attach"))
0376 goto cleanup;
0377 skel->links.urandlib_read_without_sema = l;
0378
0379 l = bpf_program__attach_usdt(skel->progs.urandlib_read_with_sema,
0380 urand_pid, "./liburandom_read.so",
0381 "urandlib", "read_with_sema", NULL);
0382 if (!ASSERT_OK_PTR(l, "urandlib_with_sema_attach"))
0383 goto cleanup;
0384 skel->links.urandlib_read_with_sema = l;
0385
0386 }
0387
0388
0389 ASSERT_OK(urand_trigger(&urand_pipe), "urand_exit_code");
0390
0391 ASSERT_EQ(bss->urand_read_without_sema_call_cnt, 1, "urand_wo_sema_cnt");
0392 ASSERT_EQ(bss->urand_read_without_sema_buf_sz_sum, 256, "urand_wo_sema_sum");
0393
0394 ASSERT_EQ(bss->urand_read_with_sema_call_cnt, 1, "urand_w_sema_cnt");
0395 ASSERT_EQ(bss->urand_read_with_sema_buf_sz_sum, 256, "urand_w_sema_sum");
0396
0397 ASSERT_EQ(bss->urandlib_read_without_sema_call_cnt, 1, "urandlib_wo_sema_cnt");
0398 ASSERT_EQ(bss->urandlib_read_without_sema_buf_sz_sum, 256, "urandlib_wo_sema_sum");
0399
0400 ASSERT_EQ(bss->urandlib_read_with_sema_call_cnt, 1, "urandlib_w_sema_cnt");
0401 ASSERT_EQ(bss->urandlib_read_with_sema_buf_sz_sum, 256, "urandlib_w_sema_sum");
0402
0403 cleanup:
0404 if (urand_pipe)
0405 pclose(urand_pipe);
0406 test_urandom_usdt__destroy(skel);
0407 }
0408
0409 void test_usdt(void)
0410 {
0411 if (test__start_subtest("basic"))
0412 subtest_basic_usdt();
0413 if (test__start_subtest("multispec"))
0414 subtest_multispec_usdt();
0415 if (test__start_subtest("urand_auto_attach"))
0416 subtest_urandom_usdt(true );
0417 if (test__start_subtest("urand_pid_attach"))
0418 subtest_urandom_usdt(false );
0419 }