12922dd58SJiri Olsa // SPDX-License-Identifier: GPL-2.0
22922dd58SJiri Olsa
32922dd58SJiri Olsa #include <test_progs.h>
42922dd58SJiri Olsa #include <bpf/btf.h>
52922dd58SJiri Olsa #include <search.h>
62922dd58SJiri Olsa #include "bpf/libbpf_internal.h"
72922dd58SJiri Olsa #include "tracing_multi.skel.h"
82863f074SJiri Olsa #include "tracing_multi_module.skel.h"
94309f580SJiri Olsa #include "tracing_multi_intersect.skel.h"
1069f25d4bSJiri Olsa #include "tracing_multi_session.skel.h"
111fd83285SJiri Olsa #include "tracing_multi_fail.skel.h"
12443c91d0SJiri Olsa #include "tracing_multi_verifier.skel.h"
134db8f60bSJiri Olsa #include "tracing_multi_bench.skel.h"
14b349efe4SJiri Olsa #include "tracing_multi_rollback.skel.h"
152922dd58SJiri Olsa #include "trace_helpers.h"
162922dd58SJiri Olsa
171b938f42SJiri Olsa static __u64 bpf_fentry_test_cookies[] = {
181b938f42SJiri Olsa 8, /* bpf_fentry_test1 */
191b938f42SJiri Olsa 9, /* bpf_fentry_test2 */
201b938f42SJiri Olsa 7, /* bpf_fentry_test3 */
211b938f42SJiri Olsa 5, /* bpf_fentry_test4 */
221b938f42SJiri Olsa 4, /* bpf_fentry_test5 */
231b938f42SJiri Olsa 2, /* bpf_fentry_test6 */
241b938f42SJiri Olsa 3, /* bpf_fentry_test7 */
251b938f42SJiri Olsa 1, /* bpf_fentry_test8 */
261b938f42SJiri Olsa 10, /* bpf_fentry_test9 */
271b938f42SJiri Olsa 6, /* bpf_fentry_test10 */
281b938f42SJiri Olsa };
291b938f42SJiri Olsa
302922dd58SJiri Olsa static const char * const bpf_fentry_test[] = {
312922dd58SJiri Olsa "bpf_fentry_test1",
322922dd58SJiri Olsa "bpf_fentry_test2",
332922dd58SJiri Olsa "bpf_fentry_test3",
342922dd58SJiri Olsa "bpf_fentry_test4",
352922dd58SJiri Olsa "bpf_fentry_test5",
362922dd58SJiri Olsa "bpf_fentry_test6",
372922dd58SJiri Olsa "bpf_fentry_test7",
382922dd58SJiri Olsa "bpf_fentry_test8",
392922dd58SJiri Olsa "bpf_fentry_test9",
402922dd58SJiri Olsa "bpf_fentry_test10",
412922dd58SJiri Olsa };
422922dd58SJiri Olsa
432863f074SJiri Olsa static const char * const bpf_testmod_fentry_test[] = {
442863f074SJiri Olsa "bpf_testmod_fentry_test1",
452863f074SJiri Olsa "bpf_testmod_fentry_test2",
462863f074SJiri Olsa "bpf_testmod_fentry_test3",
472863f074SJiri Olsa "bpf_testmod_fentry_test7",
482863f074SJiri Olsa "bpf_testmod_fentry_test11",
492863f074SJiri Olsa };
502863f074SJiri Olsa
512922dd58SJiri Olsa #define FUNCS_CNT (ARRAY_SIZE(bpf_fentry_test))
522922dd58SJiri Olsa
get_random_funcs(const char ** funcs)534309f580SJiri Olsa static int get_random_funcs(const char **funcs)
544309f580SJiri Olsa {
554309f580SJiri Olsa int i, cnt = 0;
564309f580SJiri Olsa
574309f580SJiri Olsa for (i = 0; i < FUNCS_CNT; i++) {
584309f580SJiri Olsa if (rand() % 2)
594309f580SJiri Olsa funcs[cnt++] = bpf_fentry_test[i];
604309f580SJiri Olsa }
614309f580SJiri Olsa /* we always need at least one.. */
624309f580SJiri Olsa if (!cnt)
634309f580SJiri Olsa funcs[cnt++] = bpf_fentry_test[rand() % FUNCS_CNT];
644309f580SJiri Olsa return cnt;
654309f580SJiri Olsa }
664309f580SJiri Olsa
compare(const void * ppa,const void * ppb)672922dd58SJiri Olsa static int compare(const void *ppa, const void *ppb)
682922dd58SJiri Olsa {
692922dd58SJiri Olsa const char *pa = *(const char **) ppa;
702922dd58SJiri Olsa const char *pb = *(const char **) ppb;
712922dd58SJiri Olsa
722922dd58SJiri Olsa return strcmp(pa, pb);
732922dd58SJiri Olsa }
742922dd58SJiri Olsa
tdestroy_free_nop(void * ptr)752922dd58SJiri Olsa static void tdestroy_free_nop(void *ptr)
762922dd58SJiri Olsa {
772922dd58SJiri Olsa }
782922dd58SJiri Olsa
get_ids(const char * const funcs[],int funcs_cnt,const char * mod)792922dd58SJiri Olsa static __u32 *get_ids(const char * const funcs[], int funcs_cnt, const char *mod)
802922dd58SJiri Olsa {
812922dd58SJiri Olsa struct btf *btf, *vmlinux_btf = NULL;
822922dd58SJiri Olsa __u32 nr, type_id, cnt = 0;
832922dd58SJiri Olsa void *root = NULL;
842922dd58SJiri Olsa __u32 *ids = NULL;
852922dd58SJiri Olsa int i, err = 0;
862922dd58SJiri Olsa
872922dd58SJiri Olsa btf = btf__load_vmlinux_btf();
882922dd58SJiri Olsa if (!ASSERT_OK_PTR(btf, "btf__load_vmlinux_btf"))
892922dd58SJiri Olsa return NULL;
902922dd58SJiri Olsa
912922dd58SJiri Olsa if (mod) {
922922dd58SJiri Olsa vmlinux_btf = btf;
932922dd58SJiri Olsa btf = btf__load_module_btf(mod, vmlinux_btf);
942922dd58SJiri Olsa if (!ASSERT_OK_PTR(btf, "btf__load_module_btf")) {
952922dd58SJiri Olsa btf__free(vmlinux_btf);
962922dd58SJiri Olsa return NULL;
972922dd58SJiri Olsa }
982922dd58SJiri Olsa }
992922dd58SJiri Olsa
1002922dd58SJiri Olsa ids = calloc(funcs_cnt, sizeof(ids[0]));
1012922dd58SJiri Olsa if (!ids)
1022922dd58SJiri Olsa goto out;
1032922dd58SJiri Olsa
1042922dd58SJiri Olsa /*
1052922dd58SJiri Olsa * We sort function names by name and search them
1062922dd58SJiri Olsa * below for each function.
1072922dd58SJiri Olsa */
1082922dd58SJiri Olsa for (i = 0; i < funcs_cnt; i++) {
1092922dd58SJiri Olsa if (!tsearch(&funcs[i], &root, compare)) {
1102922dd58SJiri Olsa ASSERT_FAIL("tsearch failed");
1112922dd58SJiri Olsa err = -1;
1122922dd58SJiri Olsa goto error;
1132922dd58SJiri Olsa }
1142922dd58SJiri Olsa }
1152922dd58SJiri Olsa
1162922dd58SJiri Olsa nr = btf__type_cnt(btf);
1172922dd58SJiri Olsa for (type_id = 1; type_id < nr && cnt < funcs_cnt; type_id++) {
1182922dd58SJiri Olsa const struct btf_type *type;
1192922dd58SJiri Olsa const char *str, ***val;
1202922dd58SJiri Olsa unsigned int idx;
1212922dd58SJiri Olsa
1222922dd58SJiri Olsa type = btf__type_by_id(btf, type_id);
1232922dd58SJiri Olsa if (!type) {
1242922dd58SJiri Olsa err = -1;
1252922dd58SJiri Olsa break;
1262922dd58SJiri Olsa }
1272922dd58SJiri Olsa
1282922dd58SJiri Olsa if (BTF_INFO_KIND(type->info) != BTF_KIND_FUNC)
1292922dd58SJiri Olsa continue;
1302922dd58SJiri Olsa
1312922dd58SJiri Olsa str = btf__name_by_offset(btf, type->name_off);
1322922dd58SJiri Olsa if (!str) {
1332922dd58SJiri Olsa err = -1;
1342922dd58SJiri Olsa break;
1352922dd58SJiri Olsa }
1362922dd58SJiri Olsa
1372922dd58SJiri Olsa val = tfind(&str, &root, compare);
1382922dd58SJiri Olsa if (!val)
1392922dd58SJiri Olsa continue;
1402922dd58SJiri Olsa
1412922dd58SJiri Olsa /*
1422922dd58SJiri Olsa * We keep pointer for each function name so we can get the original
1432922dd58SJiri Olsa * array index and have the resulting ids array matching the original
1442922dd58SJiri Olsa * function array.
1452922dd58SJiri Olsa *
1462922dd58SJiri Olsa * Doing it this way allow us to easily test the cookies support,
1472922dd58SJiri Olsa * because each cookie is attached to particular function/id.
1482922dd58SJiri Olsa */
1492922dd58SJiri Olsa idx = *val - funcs;
1502922dd58SJiri Olsa ids[idx] = type_id;
1512922dd58SJiri Olsa cnt++;
1522922dd58SJiri Olsa }
1532922dd58SJiri Olsa
1542922dd58SJiri Olsa error:
1552922dd58SJiri Olsa if (err) {
1562922dd58SJiri Olsa free(ids);
1572922dd58SJiri Olsa ids = NULL;
1582922dd58SJiri Olsa }
1592922dd58SJiri Olsa
1602922dd58SJiri Olsa out:
1612922dd58SJiri Olsa tdestroy(root, tdestroy_free_nop);
1622922dd58SJiri Olsa btf__free(vmlinux_btf);
1632922dd58SJiri Olsa btf__free(btf);
1642922dd58SJiri Olsa return ids;
1652922dd58SJiri Olsa }
1662922dd58SJiri Olsa
tracing_multi_test_run(struct tracing_multi * skel)1672922dd58SJiri Olsa static void tracing_multi_test_run(struct tracing_multi *skel)
1682922dd58SJiri Olsa {
1692922dd58SJiri Olsa LIBBPF_OPTS(bpf_test_run_opts, topts);
1702922dd58SJiri Olsa int err, prog_fd;
1712922dd58SJiri Olsa
1722922dd58SJiri Olsa prog_fd = bpf_program__fd(skel->progs.test_fentry);
1732922dd58SJiri Olsa err = bpf_prog_test_run_opts(prog_fd, &topts);
1742922dd58SJiri Olsa ASSERT_OK(err, "test_run");
1752922dd58SJiri Olsa
1762922dd58SJiri Olsa /* extra +1 count for sleepable programs */
1772922dd58SJiri Olsa ASSERT_EQ(skel->bss->test_result_fentry, FUNCS_CNT + 1, "test_result_fentry");
1782922dd58SJiri Olsa ASSERT_EQ(skel->bss->test_result_fexit, FUNCS_CNT + 1, "test_result_fexit");
1792922dd58SJiri Olsa }
1802922dd58SJiri Olsa
test_skel_api(void)1812922dd58SJiri Olsa static void test_skel_api(void)
1822922dd58SJiri Olsa {
1832922dd58SJiri Olsa struct tracing_multi *skel;
1842922dd58SJiri Olsa int err;
1852922dd58SJiri Olsa
1862922dd58SJiri Olsa skel = tracing_multi__open_and_load();
1872922dd58SJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi__open_and_load"))
1882922dd58SJiri Olsa return;
1892922dd58SJiri Olsa
1902922dd58SJiri Olsa skel->bss->pid = getpid();
1912922dd58SJiri Olsa
1922922dd58SJiri Olsa err = tracing_multi__attach(skel);
1932922dd58SJiri Olsa if (!ASSERT_OK(err, "tracing_multi__attach"))
1942922dd58SJiri Olsa goto cleanup;
1952922dd58SJiri Olsa
1962922dd58SJiri Olsa tracing_multi_test_run(skel);
1972922dd58SJiri Olsa
1982922dd58SJiri Olsa cleanup:
1992922dd58SJiri Olsa tracing_multi__destroy(skel);
2002922dd58SJiri Olsa }
2012922dd58SJiri Olsa
test_link_api_pattern(void)2022922dd58SJiri Olsa static void test_link_api_pattern(void)
2032922dd58SJiri Olsa {
2042922dd58SJiri Olsa struct tracing_multi *skel;
2052922dd58SJiri Olsa
2062922dd58SJiri Olsa skel = tracing_multi__open_and_load();
2072922dd58SJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi__open_and_load"))
2082922dd58SJiri Olsa return;
2092922dd58SJiri Olsa
2102922dd58SJiri Olsa skel->bss->pid = getpid();
2112922dd58SJiri Olsa
2122922dd58SJiri Olsa skel->links.test_fentry = bpf_program__attach_tracing_multi(skel->progs.test_fentry,
2132922dd58SJiri Olsa "bpf_fentry_test*", NULL);
2142922dd58SJiri Olsa if (!ASSERT_OK_PTR(skel->links.test_fentry, "bpf_program__attach_tracing_multi"))
2152922dd58SJiri Olsa goto cleanup;
2162922dd58SJiri Olsa
2172922dd58SJiri Olsa skel->links.test_fexit = bpf_program__attach_tracing_multi(skel->progs.test_fexit,
2182922dd58SJiri Olsa "bpf_fentry_test*", NULL);
2192922dd58SJiri Olsa if (!ASSERT_OK_PTR(skel->links.test_fexit, "bpf_program__attach_tracing_multi"))
2202922dd58SJiri Olsa goto cleanup;
2212922dd58SJiri Olsa
2222922dd58SJiri Olsa skel->links.test_fentry_s = bpf_program__attach_tracing_multi(skel->progs.test_fentry_s,
2232922dd58SJiri Olsa "bpf_fentry_test1", NULL);
2242922dd58SJiri Olsa if (!ASSERT_OK_PTR(skel->links.test_fentry_s, "bpf_program__attach_tracing_multi"))
2252922dd58SJiri Olsa goto cleanup;
2262922dd58SJiri Olsa
2272922dd58SJiri Olsa skel->links.test_fexit_s = bpf_program__attach_tracing_multi(skel->progs.test_fexit_s,
2282922dd58SJiri Olsa "bpf_fentry_test1", NULL);
2292922dd58SJiri Olsa if (!ASSERT_OK_PTR(skel->links.test_fexit_s, "bpf_program__attach_tracing_multi"))
2302922dd58SJiri Olsa goto cleanup;
2312922dd58SJiri Olsa
2322922dd58SJiri Olsa tracing_multi_test_run(skel);
2332922dd58SJiri Olsa
2342922dd58SJiri Olsa cleanup:
2352922dd58SJiri Olsa tracing_multi__destroy(skel);
2362922dd58SJiri Olsa }
2372922dd58SJiri Olsa
test_link_api_ids(bool test_cookies)2381b938f42SJiri Olsa static void test_link_api_ids(bool test_cookies)
2392922dd58SJiri Olsa {
2402922dd58SJiri Olsa LIBBPF_OPTS(bpf_tracing_multi_opts, opts);
2412922dd58SJiri Olsa struct tracing_multi *skel;
2422922dd58SJiri Olsa size_t cnt = FUNCS_CNT;
2432922dd58SJiri Olsa __u32 *ids;
2442922dd58SJiri Olsa
2452922dd58SJiri Olsa skel = tracing_multi__open_and_load();
2462922dd58SJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi__open_and_load"))
2472922dd58SJiri Olsa return;
2482922dd58SJiri Olsa
2492922dd58SJiri Olsa skel->bss->pid = getpid();
2501b938f42SJiri Olsa skel->bss->test_cookies = test_cookies;
2512922dd58SJiri Olsa
2522922dd58SJiri Olsa ids = get_ids(bpf_fentry_test, cnt, NULL);
2532922dd58SJiri Olsa if (!ASSERT_OK_PTR(ids, "get_ids"))
2542922dd58SJiri Olsa goto cleanup;
2552922dd58SJiri Olsa
2562922dd58SJiri Olsa opts.ids = ids;
2572922dd58SJiri Olsa opts.cnt = cnt;
2582922dd58SJiri Olsa
2591b938f42SJiri Olsa if (test_cookies)
2601b938f42SJiri Olsa opts.cookies = bpf_fentry_test_cookies;
2611b938f42SJiri Olsa
2622922dd58SJiri Olsa skel->links.test_fentry = bpf_program__attach_tracing_multi(skel->progs.test_fentry,
2632922dd58SJiri Olsa NULL, &opts);
2642922dd58SJiri Olsa if (!ASSERT_OK_PTR(skel->links.test_fentry, "bpf_program__attach_tracing_multi"))
2652922dd58SJiri Olsa goto cleanup;
2662922dd58SJiri Olsa
2672922dd58SJiri Olsa skel->links.test_fexit = bpf_program__attach_tracing_multi(skel->progs.test_fexit,
2682922dd58SJiri Olsa NULL, &opts);
2692922dd58SJiri Olsa if (!ASSERT_OK_PTR(skel->links.test_fexit, "bpf_program__attach_tracing_multi"))
2702922dd58SJiri Olsa goto cleanup;
2712922dd58SJiri Olsa
2722922dd58SJiri Olsa /* Only bpf_fentry_test1 is allowed for sleepable programs. */
2732922dd58SJiri Olsa opts.cnt = 1;
2742922dd58SJiri Olsa skel->links.test_fentry_s = bpf_program__attach_tracing_multi(skel->progs.test_fentry_s,
2752922dd58SJiri Olsa NULL, &opts);
2762922dd58SJiri Olsa if (!ASSERT_OK_PTR(skel->links.test_fentry_s, "bpf_program__attach_tracing_multi"))
2772922dd58SJiri Olsa goto cleanup;
2782922dd58SJiri Olsa
2792922dd58SJiri Olsa skel->links.test_fexit_s = bpf_program__attach_tracing_multi(skel->progs.test_fexit_s,
2802922dd58SJiri Olsa NULL, &opts);
2812922dd58SJiri Olsa if (!ASSERT_OK_PTR(skel->links.test_fexit_s, "bpf_program__attach_tracing_multi"))
2822922dd58SJiri Olsa goto cleanup;
2832922dd58SJiri Olsa
2842922dd58SJiri Olsa tracing_multi_test_run(skel);
2852922dd58SJiri Olsa
2862922dd58SJiri Olsa cleanup:
2872922dd58SJiri Olsa tracing_multi__destroy(skel);
2882922dd58SJiri Olsa free(ids);
2892922dd58SJiri Olsa }
2902922dd58SJiri Olsa
test_module_skel_api(void)2912863f074SJiri Olsa static void test_module_skel_api(void)
2922863f074SJiri Olsa {
2932863f074SJiri Olsa struct tracing_multi_module *skel = NULL;
2942863f074SJiri Olsa int err;
2952863f074SJiri Olsa
2962863f074SJiri Olsa skel = tracing_multi_module__open_and_load();
2972863f074SJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi__open_and_load"))
2982863f074SJiri Olsa return;
2992863f074SJiri Olsa
3002863f074SJiri Olsa skel->bss->pid = getpid();
3012863f074SJiri Olsa
3022863f074SJiri Olsa err = tracing_multi_module__attach(skel);
3032863f074SJiri Olsa if (!ASSERT_OK(err, "tracing_multi__attach"))
3042863f074SJiri Olsa goto cleanup;
3052863f074SJiri Olsa
3062863f074SJiri Olsa ASSERT_OK(trigger_module_test_read(1), "trigger_read");
3072863f074SJiri Olsa ASSERT_EQ(skel->bss->test_result_fentry, 5, "test_result_fentry");
3082863f074SJiri Olsa ASSERT_EQ(skel->bss->test_result_fexit, 5, "test_result_fexit");
3092863f074SJiri Olsa
3102863f074SJiri Olsa cleanup:
3112863f074SJiri Olsa tracing_multi_module__destroy(skel);
3122863f074SJiri Olsa }
3132863f074SJiri Olsa
test_module_link_api_pattern(void)3142863f074SJiri Olsa static void test_module_link_api_pattern(void)
3152863f074SJiri Olsa {
3162863f074SJiri Olsa struct tracing_multi_module *skel = NULL;
3172863f074SJiri Olsa
3182863f074SJiri Olsa skel = tracing_multi_module__open_and_load();
3192863f074SJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi_module__open_and_load"))
3202863f074SJiri Olsa return;
3212863f074SJiri Olsa
3222863f074SJiri Olsa skel->bss->pid = getpid();
3232863f074SJiri Olsa
3242863f074SJiri Olsa skel->links.test_fentry = bpf_program__attach_tracing_multi(skel->progs.test_fentry,
3252863f074SJiri Olsa "bpf_testmod:bpf_testmod_fentry_test*", NULL);
3262863f074SJiri Olsa if (!ASSERT_OK_PTR(skel->links.test_fentry, "bpf_program__attach_tracing_multi"))
3272863f074SJiri Olsa goto cleanup;
3282863f074SJiri Olsa
3292863f074SJiri Olsa skel->links.test_fexit = bpf_program__attach_tracing_multi(skel->progs.test_fexit,
3302863f074SJiri Olsa "bpf_testmod:bpf_testmod_fentry_test*", NULL);
3312863f074SJiri Olsa if (!ASSERT_OK_PTR(skel->links.test_fexit, "bpf_program__attach_tracing_multi"))
3322863f074SJiri Olsa goto cleanup;
3332863f074SJiri Olsa
3342863f074SJiri Olsa ASSERT_OK(trigger_module_test_read(1), "trigger_read");
3352863f074SJiri Olsa ASSERT_EQ(skel->bss->test_result_fentry, 5, "test_result_fentry");
3362863f074SJiri Olsa ASSERT_EQ(skel->bss->test_result_fexit, 5, "test_result_fexit");
3372863f074SJiri Olsa
3382863f074SJiri Olsa cleanup:
3392863f074SJiri Olsa tracing_multi_module__destroy(skel);
3402863f074SJiri Olsa }
3412863f074SJiri Olsa
test_module_link_api_ids(void)3422863f074SJiri Olsa static void test_module_link_api_ids(void)
3432863f074SJiri Olsa {
3442863f074SJiri Olsa size_t cnt = ARRAY_SIZE(bpf_testmod_fentry_test);
3452863f074SJiri Olsa LIBBPF_OPTS(bpf_tracing_multi_opts, opts);
3462863f074SJiri Olsa struct tracing_multi_module *skel = NULL;
3472863f074SJiri Olsa __u32 *ids;
3482863f074SJiri Olsa
3492863f074SJiri Olsa skel = tracing_multi_module__open_and_load();
3502863f074SJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi_module__open_and_load"))
3512863f074SJiri Olsa return;
3522863f074SJiri Olsa
3532863f074SJiri Olsa skel->bss->pid = getpid();
3542863f074SJiri Olsa
3552863f074SJiri Olsa ids = get_ids(bpf_testmod_fentry_test, cnt, "bpf_testmod");
3562863f074SJiri Olsa if (!ASSERT_OK_PTR(ids, "get_ids"))
3572863f074SJiri Olsa goto cleanup;
3582863f074SJiri Olsa
3592863f074SJiri Olsa opts.ids = ids;
3602863f074SJiri Olsa opts.cnt = cnt;
3612863f074SJiri Olsa
3622863f074SJiri Olsa skel->links.test_fentry = bpf_program__attach_tracing_multi(skel->progs.test_fentry,
3632863f074SJiri Olsa NULL, &opts);
3642863f074SJiri Olsa if (!ASSERT_OK_PTR(skel->links.test_fentry, "bpf_program__attach_tracing_multi"))
3652863f074SJiri Olsa goto cleanup;
3662863f074SJiri Olsa
3672863f074SJiri Olsa skel->links.test_fexit = bpf_program__attach_tracing_multi(skel->progs.test_fexit,
3682863f074SJiri Olsa NULL, &opts);
3692863f074SJiri Olsa if (!ASSERT_OK_PTR(skel->links.test_fexit, "bpf_program__attach_tracing_multi"))
3702863f074SJiri Olsa goto cleanup;
3712863f074SJiri Olsa
3722863f074SJiri Olsa ASSERT_OK(trigger_module_test_read(1), "trigger_read");
3732863f074SJiri Olsa ASSERT_EQ(skel->bss->test_result_fentry, 5, "test_result_fentry");
3742863f074SJiri Olsa ASSERT_EQ(skel->bss->test_result_fexit, 5, "test_result_fexit");
3752863f074SJiri Olsa
3762863f074SJiri Olsa cleanup:
3772863f074SJiri Olsa tracing_multi_module__destroy(skel);
3782863f074SJiri Olsa free(ids);
3792863f074SJiri Olsa }
3802863f074SJiri Olsa
is_set(__u32 mask,__u32 bit)3814309f580SJiri Olsa static bool is_set(__u32 mask, __u32 bit)
3824309f580SJiri Olsa {
3834309f580SJiri Olsa return (1 << bit) & mask;
3844309f580SJiri Olsa }
3854309f580SJiri Olsa
__test_intersect(__u32 mask,const struct bpf_program * progs[4],__u64 * test_results[4])3864309f580SJiri Olsa static void __test_intersect(__u32 mask, const struct bpf_program *progs[4], __u64 *test_results[4])
3874309f580SJiri Olsa {
3884309f580SJiri Olsa LIBBPF_OPTS(bpf_tracing_multi_opts, opts);
3894309f580SJiri Olsa LIBBPF_OPTS(bpf_test_run_opts, topts);
3904309f580SJiri Olsa struct bpf_link *links[4] = { NULL };
3914309f580SJiri Olsa const char *funcs[FUNCS_CNT];
3924309f580SJiri Olsa __u64 expected[4];
3934309f580SJiri Olsa __u32 *ids, i;
3944309f580SJiri Olsa int err, cnt;
3954309f580SJiri Olsa
3964309f580SJiri Olsa /*
3974309f580SJiri Olsa * We have 4 programs in progs and the mask bits pick which
3984309f580SJiri Olsa * of them gets attached to randomly chosen functions.
3994309f580SJiri Olsa */
4004309f580SJiri Olsa for (i = 0; i < 4; i++) {
4014309f580SJiri Olsa if (!is_set(mask, i))
4024309f580SJiri Olsa continue;
4034309f580SJiri Olsa
4044309f580SJiri Olsa cnt = get_random_funcs(funcs);
4054309f580SJiri Olsa ids = get_ids(funcs, cnt, NULL);
4064309f580SJiri Olsa if (!ASSERT_OK_PTR(ids, "get_ids"))
4074309f580SJiri Olsa goto cleanup;
4084309f580SJiri Olsa
4094309f580SJiri Olsa opts.ids = ids;
4104309f580SJiri Olsa opts.cnt = cnt;
4114309f580SJiri Olsa links[i] = bpf_program__attach_tracing_multi(progs[i], NULL, &opts);
4124309f580SJiri Olsa free(ids);
4134309f580SJiri Olsa
4144309f580SJiri Olsa if (!ASSERT_OK_PTR(links[i], "bpf_program__attach_tracing_multi"))
4154309f580SJiri Olsa goto cleanup;
4164309f580SJiri Olsa
4174309f580SJiri Olsa expected[i] = *test_results[i] + cnt;
4184309f580SJiri Olsa }
4194309f580SJiri Olsa
4204309f580SJiri Olsa err = bpf_prog_test_run_opts(bpf_program__fd(progs[0]), &topts);
4214309f580SJiri Olsa ASSERT_OK(err, "test_run");
4224309f580SJiri Olsa
4234309f580SJiri Olsa for (i = 0; i < 4; i++) {
4244309f580SJiri Olsa if (!is_set(mask, i))
4254309f580SJiri Olsa continue;
4264309f580SJiri Olsa ASSERT_EQ(*test_results[i], expected[i], "test_results");
4274309f580SJiri Olsa }
4284309f580SJiri Olsa
4294309f580SJiri Olsa cleanup:
4304309f580SJiri Olsa for (i = 0; i < 4; i++)
4314309f580SJiri Olsa bpf_link__destroy(links[i]);
4324309f580SJiri Olsa }
4334309f580SJiri Olsa
test_intersect(void)4344309f580SJiri Olsa static void test_intersect(void)
4354309f580SJiri Olsa {
4364309f580SJiri Olsa struct tracing_multi_intersect *skel;
4374309f580SJiri Olsa const struct bpf_program *progs[4];
4384309f580SJiri Olsa __u64 *test_results[4];
4394309f580SJiri Olsa __u32 i;
4404309f580SJiri Olsa
4414309f580SJiri Olsa skel = tracing_multi_intersect__open_and_load();
4424309f580SJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi_intersect__open_and_load"))
4434309f580SJiri Olsa return;
4444309f580SJiri Olsa
4454309f580SJiri Olsa skel->bss->pid = getpid();
4464309f580SJiri Olsa
4474309f580SJiri Olsa progs[0] = skel->progs.fentry_1;
4484309f580SJiri Olsa progs[1] = skel->progs.fexit_1;
4494309f580SJiri Olsa progs[2] = skel->progs.fentry_2;
4504309f580SJiri Olsa progs[3] = skel->progs.fexit_2;
4514309f580SJiri Olsa
4524309f580SJiri Olsa test_results[0] = &skel->bss->test_result_fentry_1;
4534309f580SJiri Olsa test_results[1] = &skel->bss->test_result_fexit_1;
4544309f580SJiri Olsa test_results[2] = &skel->bss->test_result_fentry_2;
4554309f580SJiri Olsa test_results[3] = &skel->bss->test_result_fexit_2;
4564309f580SJiri Olsa
4574309f580SJiri Olsa for (i = 1; i < 16; i++)
4584309f580SJiri Olsa __test_intersect(i, progs, test_results);
4594309f580SJiri Olsa
4604309f580SJiri Olsa tracing_multi_intersect__destroy(skel);
4614309f580SJiri Olsa }
4624309f580SJiri Olsa
test_fentry_after_multi(void)463*539d3edfSLeon Hwang static void test_fentry_after_multi(void)
464*539d3edfSLeon Hwang {
465*539d3edfSLeon Hwang static const char * const funcs[] = {
466*539d3edfSLeon Hwang "bpf_fentry_test1",
467*539d3edfSLeon Hwang };
468*539d3edfSLeon Hwang struct bpf_link *fentry_link = NULL, *multi_link = NULL;
469*539d3edfSLeon Hwang struct tracing_multi_intersect *skel = NULL;
470*539d3edfSLeon Hwang LIBBPF_OPTS(bpf_tracing_multi_opts, opts);
471*539d3edfSLeon Hwang LIBBPF_OPTS(bpf_test_run_opts, topts);
472*539d3edfSLeon Hwang __u32 *ids = NULL;
473*539d3edfSLeon Hwang int err;
474*539d3edfSLeon Hwang
475*539d3edfSLeon Hwang skel = tracing_multi_intersect__open_and_load();
476*539d3edfSLeon Hwang if (!ASSERT_OK_PTR(skel, "tracing_multi_intersect__open_and_load"))
477*539d3edfSLeon Hwang return;
478*539d3edfSLeon Hwang
479*539d3edfSLeon Hwang skel->bss->pid = getpid();
480*539d3edfSLeon Hwang
481*539d3edfSLeon Hwang ids = get_ids(funcs, ARRAY_SIZE(funcs), NULL);
482*539d3edfSLeon Hwang if (!ASSERT_OK_PTR(ids, "get_ids"))
483*539d3edfSLeon Hwang goto cleanup;
484*539d3edfSLeon Hwang
485*539d3edfSLeon Hwang opts.ids = ids;
486*539d3edfSLeon Hwang opts.cnt = ARRAY_SIZE(funcs);
487*539d3edfSLeon Hwang multi_link = bpf_program__attach_tracing_multi(skel->progs.fentry_1, NULL, &opts);
488*539d3edfSLeon Hwang if (!ASSERT_OK_PTR(multi_link, "attach_multi"))
489*539d3edfSLeon Hwang goto cleanup;
490*539d3edfSLeon Hwang
491*539d3edfSLeon Hwang fentry_link = bpf_program__attach(skel->progs.fentry);
492*539d3edfSLeon Hwang if (!ASSERT_OK_PTR(fentry_link, "attach_fentry"))
493*539d3edfSLeon Hwang goto cleanup;
494*539d3edfSLeon Hwang
495*539d3edfSLeon Hwang err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.fentry_1), &topts);
496*539d3edfSLeon Hwang if (!ASSERT_OK(err, "test_run"))
497*539d3edfSLeon Hwang goto cleanup;
498*539d3edfSLeon Hwang ASSERT_EQ(skel->bss->test_result_fentry_1, 1, "multi_fentry");
499*539d3edfSLeon Hwang ASSERT_EQ(skel->bss->test_result_fentry, 1, "fentry");
500*539d3edfSLeon Hwang
501*539d3edfSLeon Hwang err = bpf_link__destroy(fentry_link);
502*539d3edfSLeon Hwang fentry_link = NULL;
503*539d3edfSLeon Hwang if (!ASSERT_OK(err, "destroy_fentry"))
504*539d3edfSLeon Hwang goto cleanup;
505*539d3edfSLeon Hwang
506*539d3edfSLeon Hwang err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.fentry_1), &topts);
507*539d3edfSLeon Hwang if (!ASSERT_OK(err, "test_run_multi"))
508*539d3edfSLeon Hwang goto cleanup;
509*539d3edfSLeon Hwang ASSERT_EQ(skel->bss->test_result_fentry_1, 2, "multi_fentry_only");
510*539d3edfSLeon Hwang ASSERT_EQ(skel->bss->test_result_fentry, 1, "fentry_detached");
511*539d3edfSLeon Hwang
512*539d3edfSLeon Hwang err = bpf_link__destroy(multi_link);
513*539d3edfSLeon Hwang multi_link = NULL;
514*539d3edfSLeon Hwang if (!ASSERT_OK(err, "destroy_multi"))
515*539d3edfSLeon Hwang goto cleanup;
516*539d3edfSLeon Hwang
517*539d3edfSLeon Hwang err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.fentry_1), &topts);
518*539d3edfSLeon Hwang if (!ASSERT_OK(err, "test_run_detached"))
519*539d3edfSLeon Hwang goto cleanup;
520*539d3edfSLeon Hwang ASSERT_EQ(skel->bss->test_result_fentry_1, 2, "multi_fentry_detached");
521*539d3edfSLeon Hwang ASSERT_EQ(skel->bss->test_result_fentry, 1, "fentry_still_detached");
522*539d3edfSLeon Hwang
523*539d3edfSLeon Hwang cleanup:
524*539d3edfSLeon Hwang bpf_link__destroy(fentry_link);
525*539d3edfSLeon Hwang bpf_link__destroy(multi_link);
526*539d3edfSLeon Hwang free(ids);
527*539d3edfSLeon Hwang tracing_multi_intersect__destroy(skel);
528*539d3edfSLeon Hwang }
529*539d3edfSLeon Hwang
test_session(void)53069f25d4bSJiri Olsa static void test_session(void)
53169f25d4bSJiri Olsa {
53269f25d4bSJiri Olsa LIBBPF_OPTS(bpf_test_run_opts, topts);
53369f25d4bSJiri Olsa struct tracing_multi_session *skel;
53469f25d4bSJiri Olsa int err, prog_fd;
53569f25d4bSJiri Olsa
53669f25d4bSJiri Olsa skel = tracing_multi_session__open_and_load();
53769f25d4bSJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi_session__open_and_load"))
53869f25d4bSJiri Olsa return;
53969f25d4bSJiri Olsa
54069f25d4bSJiri Olsa skel->bss->pid = getpid();
54169f25d4bSJiri Olsa
54269f25d4bSJiri Olsa err = tracing_multi_session__attach(skel);
54369f25d4bSJiri Olsa if (!ASSERT_OK(err, "tracing_multi_session__attach"))
54469f25d4bSJiri Olsa goto cleanup;
54569f25d4bSJiri Olsa
54669f25d4bSJiri Olsa /* execute kernel session */
54769f25d4bSJiri Olsa prog_fd = bpf_program__fd(skel->progs.test_session_1);
54869f25d4bSJiri Olsa err = bpf_prog_test_run_opts(prog_fd, &topts);
54969f25d4bSJiri Olsa ASSERT_OK(err, "test_run");
55069f25d4bSJiri Olsa
55169f25d4bSJiri Olsa /* 10 for test_session_1, 1 for test_fsession_s */
55269f25d4bSJiri Olsa ASSERT_EQ(skel->bss->test_result_fentry, 11, "test_result_fentry");
55369f25d4bSJiri Olsa /* extra count (+1 for each fexit execution) for test_result_fexit cookie check/inc */
55469f25d4bSJiri Olsa ASSERT_EQ(skel->bss->test_result_fexit, 22, "test_result_fexit");
55569f25d4bSJiri Olsa
55669f25d4bSJiri Olsa skel->bss->test_result_fentry = 0;
55769f25d4bSJiri Olsa skel->bss->test_result_fexit = 0;
55869f25d4bSJiri Olsa
55969f25d4bSJiri Olsa /* execute bpf_testmo.ko session */
56069f25d4bSJiri Olsa ASSERT_OK(trigger_module_test_read(1), "trigger_read");
56169f25d4bSJiri Olsa
56269f25d4bSJiri Olsa /* 5 for test_session_2 */
56369f25d4bSJiri Olsa ASSERT_EQ(skel->bss->test_result_fentry, 5, "test_result_fentry");
56469f25d4bSJiri Olsa /* extra count (+1 for each fexit execution) for test_result_fexit cookie */
56569f25d4bSJiri Olsa ASSERT_EQ(skel->bss->test_result_fexit, 10, "test_result_fexit");
56669f25d4bSJiri Olsa
56769f25d4bSJiri Olsa
56869f25d4bSJiri Olsa cleanup:
56969f25d4bSJiri Olsa tracing_multi_session__destroy(skel);
57069f25d4bSJiri Olsa }
57169f25d4bSJiri Olsa
test_attach_api_fails(void)5721fd83285SJiri Olsa static void test_attach_api_fails(void)
5731fd83285SJiri Olsa {
5741fd83285SJiri Olsa LIBBPF_OPTS(bpf_tracing_multi_opts, opts);
5751fd83285SJiri Olsa static const char * const func[] = {
5761fd83285SJiri Olsa "bpf_fentry_test2",
5771fd83285SJiri Olsa };
5781fd83285SJiri Olsa struct tracing_multi_fail *skel = NULL;
5791fd83285SJiri Olsa __u32 ids[2] = {}, *ids2 = NULL;
5801fd83285SJiri Olsa __u64 cookies[2];
5811fd83285SJiri Olsa
5821fd83285SJiri Olsa skel = tracing_multi_fail__open_and_load();
5831fd83285SJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi_fail__open_and_load"))
5841fd83285SJiri Olsa return;
5851fd83285SJiri Olsa
5861fd83285SJiri Olsa /* fail#1 (libbpf) pattern and opts NULL */
5871fd83285SJiri Olsa skel->links.test_fentry = bpf_program__attach_tracing_multi(skel->progs.test_fentry,
5881fd83285SJiri Olsa NULL, NULL);
5891fd83285SJiri Olsa if (!ASSERT_EQ(libbpf_get_error(skel->links.test_fentry), -EINVAL, "fail_1"))
5901fd83285SJiri Olsa goto cleanup;
5911fd83285SJiri Olsa
5921fd83285SJiri Olsa /* fail#2 (libbpf) pattern and ids */
5931fd83285SJiri Olsa LIBBPF_OPTS_RESET(opts,
5941fd83285SJiri Olsa .ids = ids,
5951fd83285SJiri Olsa .cnt = 2,
5961fd83285SJiri Olsa );
5971fd83285SJiri Olsa
5981fd83285SJiri Olsa skel->links.test_fentry = bpf_program__attach_tracing_multi(skel->progs.test_fentry,
5991fd83285SJiri Olsa "bpf_fentry_test*", &opts);
6001fd83285SJiri Olsa if (!ASSERT_EQ(libbpf_get_error(skel->links.test_fentry), -EINVAL, "fail_2"))
6011fd83285SJiri Olsa goto cleanup;
6021fd83285SJiri Olsa
6031fd83285SJiri Olsa /* fail#3 (libbpf) pattern and cookies */
6041fd83285SJiri Olsa LIBBPF_OPTS_RESET(opts,
6051fd83285SJiri Olsa .ids = NULL,
6061fd83285SJiri Olsa .cnt = 2,
6071fd83285SJiri Olsa .cookies = cookies,
6081fd83285SJiri Olsa );
6091fd83285SJiri Olsa
6101fd83285SJiri Olsa skel->links.test_fentry = bpf_program__attach_tracing_multi(skel->progs.test_fentry,
6111fd83285SJiri Olsa "bpf_fentry_test*", &opts);
6121fd83285SJiri Olsa if (!ASSERT_EQ(libbpf_get_error(skel->links.test_fentry), -EINVAL, "fail_3"))
6131fd83285SJiri Olsa goto cleanup;
6141fd83285SJiri Olsa
6151fd83285SJiri Olsa /* fail#4 (libbpf) bogus pattern */
6161fd83285SJiri Olsa skel->links.test_fentry = bpf_program__attach_tracing_multi(skel->progs.test_fentry,
6171fd83285SJiri Olsa "bpf_not_really_a_function*", NULL);
6181fd83285SJiri Olsa if (!ASSERT_EQ(libbpf_get_error(skel->links.test_fentry), -EINVAL, "fail_4"))
6191fd83285SJiri Olsa goto cleanup;
6201fd83285SJiri Olsa
6211fd83285SJiri Olsa /* fail#5 (kernel) abnormal cnt */
6221fd83285SJiri Olsa LIBBPF_OPTS_RESET(opts,
6231fd83285SJiri Olsa .ids = ids,
6241fd83285SJiri Olsa .cnt = INT_MAX,
6251fd83285SJiri Olsa );
6261fd83285SJiri Olsa
6271fd83285SJiri Olsa skel->links.test_fentry = bpf_program__attach_tracing_multi(skel->progs.test_fentry,
6281fd83285SJiri Olsa NULL, &opts);
6291fd83285SJiri Olsa if (!ASSERT_EQ(libbpf_get_error(skel->links.test_fentry), -E2BIG, "fail_5"))
6301fd83285SJiri Olsa goto cleanup;
6311fd83285SJiri Olsa
6321fd83285SJiri Olsa /* fail#6 (kernel) attach sleepable program to not-allowed function */
6331fd83285SJiri Olsa ids2 = get_ids(func, 1, NULL);
6341fd83285SJiri Olsa if (!ASSERT_OK_PTR(ids2, "get_ids"))
6351fd83285SJiri Olsa goto cleanup;
6361fd83285SJiri Olsa
6371fd83285SJiri Olsa LIBBPF_OPTS_RESET(opts,
6381fd83285SJiri Olsa .ids = ids2,
6391fd83285SJiri Olsa .cnt = 1,
6401fd83285SJiri Olsa );
6411fd83285SJiri Olsa
6421fd83285SJiri Olsa skel->links.test_fentry_s = bpf_program__attach_tracing_multi(skel->progs.test_fentry_s,
6431fd83285SJiri Olsa NULL, &opts);
6441fd83285SJiri Olsa if (!ASSERT_EQ(libbpf_get_error(skel->links.test_fentry_s), -EINVAL, "fail_6"))
6451fd83285SJiri Olsa goto cleanup;
6461fd83285SJiri Olsa
6471fd83285SJiri Olsa /* fail#7 (kernel) attach with duplicate id */
6481fd83285SJiri Olsa ids[0] = ids2[0];
6491fd83285SJiri Olsa ids[1] = ids2[0];
6501fd83285SJiri Olsa
6511fd83285SJiri Olsa LIBBPF_OPTS_RESET(opts,
6521fd83285SJiri Olsa .ids = ids,
6531fd83285SJiri Olsa .cnt = 2,
6541fd83285SJiri Olsa );
6551fd83285SJiri Olsa
6561fd83285SJiri Olsa skel->links.test_fentry = bpf_program__attach_tracing_multi(skel->progs.test_fentry,
6571fd83285SJiri Olsa NULL, &opts);
6581fd83285SJiri Olsa ASSERT_EQ(libbpf_get_error(skel->links.test_fentry), -EINVAL, "fail_7");
6591fd83285SJiri Olsa
6601fd83285SJiri Olsa cleanup:
6611fd83285SJiri Olsa tracing_multi_fail__destroy(skel);
6621fd83285SJiri Olsa free(ids2);
6631fd83285SJiri Olsa }
6641fd83285SJiri Olsa
serial_test_tracing_multi_bench_attach(void)6654db8f60bSJiri Olsa void serial_test_tracing_multi_bench_attach(void)
6664db8f60bSJiri Olsa {
6674db8f60bSJiri Olsa LIBBPF_OPTS(bpf_tracing_multi_opts, opts);
6684db8f60bSJiri Olsa struct tracing_multi_bench *skel = NULL;
6694db8f60bSJiri Olsa long attach_start_ns, attach_end_ns;
6704db8f60bSJiri Olsa long detach_start_ns, detach_end_ns;
6714db8f60bSJiri Olsa double attach_delta, detach_delta;
6724db8f60bSJiri Olsa struct bpf_link *link = NULL;
6734db8f60bSJiri Olsa size_t i, cap = 0, cnt = 0;
6744db8f60bSJiri Olsa struct ksyms *ksyms = NULL;
6754db8f60bSJiri Olsa void *root = NULL;
6764db8f60bSJiri Olsa void *dups = NULL;
6774db8f60bSJiri Olsa __u32 *ids = NULL;
6784db8f60bSJiri Olsa __u32 nr, type_id;
6794db8f60bSJiri Olsa struct btf *btf;
6804db8f60bSJiri Olsa int err;
6814db8f60bSJiri Olsa
6824db8f60bSJiri Olsa #ifndef __x86_64__
6834db8f60bSJiri Olsa test__skip();
6844db8f60bSJiri Olsa return;
6854db8f60bSJiri Olsa #endif
6864db8f60bSJiri Olsa
6874db8f60bSJiri Olsa btf = btf__load_vmlinux_btf();
6884db8f60bSJiri Olsa if (!ASSERT_OK_PTR(btf, "btf__load_vmlinux_btf"))
6894db8f60bSJiri Olsa return;
6904db8f60bSJiri Olsa
6914db8f60bSJiri Olsa skel = tracing_multi_bench__open_and_load();
6924db8f60bSJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi_bench__open_and_load"))
6934db8f60bSJiri Olsa goto cleanup;
6944db8f60bSJiri Olsa
6954db8f60bSJiri Olsa if (!ASSERT_OK(bpf_get_ksyms(&ksyms, true), "get_syms"))
6964db8f60bSJiri Olsa goto cleanup;
6974db8f60bSJiri Olsa
6984db8f60bSJiri Olsa /* Get all ftrace 'safe' symbols.. */
6994db8f60bSJiri Olsa for (i = 0; i < ksyms->filtered_cnt; i++) {
7004db8f60bSJiri Olsa if (!tsearch(&ksyms->filtered_syms[i], &root, compare)) {
7014db8f60bSJiri Olsa ASSERT_FAIL("tsearch failed");
7024db8f60bSJiri Olsa goto cleanup;
7034db8f60bSJiri Olsa }
7044db8f60bSJiri Olsa }
7054db8f60bSJiri Olsa
7064db8f60bSJiri Olsa /*
7074db8f60bSJiri Olsa * Collect names that are not unique in kallsyms. The kernel resolves a
7084db8f60bSJiri Olsa * tracing-multi BTF id to an address with kallsyms_lookup_name(), which
7094db8f60bSJiri Olsa * returns the first symbol of that name. For a duplicate name that may
7104db8f60bSJiri Olsa * be a different (non-ftrace-able) instance than the ftrace-able one in
7114db8f60bSJiri Olsa * available_filter_functions, so attaching to it by BTF id fails with
7124db8f60bSJiri Olsa * -ENOENT (e.g. t_start/t_next/t_stop). ksyms->syms is sorted by name,
7134db8f60bSJiri Olsa * so equal names are adjacent.
7144db8f60bSJiri Olsa */
7154db8f60bSJiri Olsa for (i = 1; i < ksyms->sym_cnt; i++) {
7164db8f60bSJiri Olsa if (strcmp(ksyms->syms[i].name, ksyms->syms[i - 1].name))
7174db8f60bSJiri Olsa continue;
7184db8f60bSJiri Olsa if (!tsearch(&ksyms->syms[i].name, &dups, compare)) {
7194db8f60bSJiri Olsa ASSERT_FAIL("tsearch failed");
7204db8f60bSJiri Olsa goto cleanup;
7214db8f60bSJiri Olsa }
7224db8f60bSJiri Olsa }
7234db8f60bSJiri Olsa
7244db8f60bSJiri Olsa /* ..and filter them through BTF and btf_type_is_traceable_func. */
7254db8f60bSJiri Olsa nr = btf__type_cnt(btf);
7264db8f60bSJiri Olsa for (type_id = 1; type_id < nr; type_id++) {
7274db8f60bSJiri Olsa const struct btf_type *type;
7284db8f60bSJiri Olsa const char *str;
7294db8f60bSJiri Olsa
7304db8f60bSJiri Olsa type = btf__type_by_id(btf, type_id);
7314db8f60bSJiri Olsa if (!type)
7324db8f60bSJiri Olsa break;
7334db8f60bSJiri Olsa
7344db8f60bSJiri Olsa if (BTF_INFO_KIND(type->info) != BTF_KIND_FUNC)
7354db8f60bSJiri Olsa continue;
7364db8f60bSJiri Olsa
7374db8f60bSJiri Olsa str = btf__name_by_offset(btf, type->name_off);
7384db8f60bSJiri Olsa if (!str)
7394db8f60bSJiri Olsa break;
7404db8f60bSJiri Olsa
7414db8f60bSJiri Olsa if (!tfind(&str, &root, compare))
7424db8f60bSJiri Olsa continue;
7434db8f60bSJiri Olsa
7444db8f60bSJiri Olsa /* Skip names that are not unique in kallsyms, see above. */
7454db8f60bSJiri Olsa if (tfind(&str, &dups, compare))
7464db8f60bSJiri Olsa continue;
7474db8f60bSJiri Olsa
7484db8f60bSJiri Olsa if (!btf_type_is_traceable_func(btf, type))
7494db8f60bSJiri Olsa continue;
7504db8f60bSJiri Olsa
7514db8f60bSJiri Olsa err = libbpf_ensure_mem((void **) &ids, &cap, sizeof(*ids), cnt + 1);
7524db8f60bSJiri Olsa if (err)
7534db8f60bSJiri Olsa goto cleanup;
7544db8f60bSJiri Olsa
7554db8f60bSJiri Olsa ids[cnt++] = type_id;
7564db8f60bSJiri Olsa }
7574db8f60bSJiri Olsa
7584db8f60bSJiri Olsa opts.ids = ids;
7594db8f60bSJiri Olsa opts.cnt = cnt;
7604db8f60bSJiri Olsa
7614db8f60bSJiri Olsa attach_start_ns = get_time_ns();
7624db8f60bSJiri Olsa link = bpf_program__attach_tracing_multi(skel->progs.bench, NULL, &opts);
7634db8f60bSJiri Olsa attach_end_ns = get_time_ns();
7644db8f60bSJiri Olsa
7654db8f60bSJiri Olsa if (!ASSERT_OK_PTR(link, "bpf_program__attach_tracing_multi"))
7664db8f60bSJiri Olsa goto cleanup;
7674db8f60bSJiri Olsa
7684db8f60bSJiri Olsa detach_start_ns = get_time_ns();
7694db8f60bSJiri Olsa bpf_link__destroy(link);
7704db8f60bSJiri Olsa detach_end_ns = get_time_ns();
7714db8f60bSJiri Olsa
7724db8f60bSJiri Olsa attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0;
7734db8f60bSJiri Olsa detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0;
7744db8f60bSJiri Olsa
7754db8f60bSJiri Olsa printf("%s: found %lu functions\n", __func__, cnt);
7764db8f60bSJiri Olsa printf("%s: attached in %7.3lfs\n", __func__, attach_delta);
7774db8f60bSJiri Olsa printf("%s: detached in %7.3lfs\n", __func__, detach_delta);
7784db8f60bSJiri Olsa
7794db8f60bSJiri Olsa cleanup:
7804db8f60bSJiri Olsa tracing_multi_bench__destroy(skel);
7814db8f60bSJiri Olsa tdestroy(root, tdestroy_free_nop);
7824db8f60bSJiri Olsa tdestroy(dups, tdestroy_free_nop);
7834db8f60bSJiri Olsa free_kallsyms_local(ksyms);
7844db8f60bSJiri Olsa free(ids);
7854db8f60bSJiri Olsa btf__free(btf);
7864db8f60bSJiri Olsa }
7874db8f60bSJiri Olsa
tracing_multi_rollback_run(struct tracing_multi_rollback * skel)788b349efe4SJiri Olsa static void tracing_multi_rollback_run(struct tracing_multi_rollback *skel)
789b349efe4SJiri Olsa {
790b349efe4SJiri Olsa LIBBPF_OPTS(bpf_test_run_opts, topts);
791b349efe4SJiri Olsa int err, prog_fd;
792b349efe4SJiri Olsa
793b349efe4SJiri Olsa prog_fd = bpf_program__fd(skel->progs.test_fentry);
794b349efe4SJiri Olsa err = bpf_prog_test_run_opts(prog_fd, &topts);
795b349efe4SJiri Olsa ASSERT_OK(err, "test_run");
796b349efe4SJiri Olsa
797b349efe4SJiri Olsa /* make sure the rollback code did not leave any program attached */
798b349efe4SJiri Olsa ASSERT_EQ(skel->bss->test_result_fentry, 0, "test_result_fentry");
799b349efe4SJiri Olsa ASSERT_EQ(skel->bss->test_result_fexit, 0, "test_result_fexit");
800b349efe4SJiri Olsa }
801b349efe4SJiri Olsa
test_rollback_put(void)802b349efe4SJiri Olsa static void test_rollback_put(void)
803b349efe4SJiri Olsa {
804b349efe4SJiri Olsa LIBBPF_OPTS(bpf_tracing_multi_opts, opts);
805b349efe4SJiri Olsa struct tracing_multi_rollback *skel = NULL;
806b349efe4SJiri Olsa size_t cnt = FUNCS_CNT;
807b349efe4SJiri Olsa __u32 *ids = NULL;
808b349efe4SJiri Olsa int err;
809b349efe4SJiri Olsa
810b349efe4SJiri Olsa skel = tracing_multi_rollback__open();
811b349efe4SJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi_rollback__open"))
812b349efe4SJiri Olsa return;
813b349efe4SJiri Olsa
814b349efe4SJiri Olsa bpf_program__set_autoload(skel->progs.test_fentry, true);
815b349efe4SJiri Olsa bpf_program__set_autoload(skel->progs.test_fexit, true);
816b349efe4SJiri Olsa
817b349efe4SJiri Olsa err = tracing_multi_rollback__load(skel);
818b349efe4SJiri Olsa if (!ASSERT_OK(err, "tracing_multi_rollback__load"))
819b349efe4SJiri Olsa goto cleanup;
820b349efe4SJiri Olsa
821b349efe4SJiri Olsa ids = get_ids(bpf_fentry_test, cnt, NULL);
822b349efe4SJiri Olsa if (!ASSERT_OK_PTR(ids, "get_ids"))
823b349efe4SJiri Olsa goto cleanup;
824b349efe4SJiri Olsa
825b349efe4SJiri Olsa /*
826b349efe4SJiri Olsa * Mangle last id to trigger rollback, which needs to do put
827b349efe4SJiri Olsa * on get-ed trampolines.
828b349efe4SJiri Olsa */
829b349efe4SJiri Olsa ids[9] = 0;
830b349efe4SJiri Olsa
831b349efe4SJiri Olsa opts.ids = ids;
832b349efe4SJiri Olsa opts.cnt = cnt;
833b349efe4SJiri Olsa
834b349efe4SJiri Olsa skel->bss->pid = getpid();
835b349efe4SJiri Olsa
836b349efe4SJiri Olsa skel->links.test_fentry = bpf_program__attach_tracing_multi(skel->progs.test_fentry,
837b349efe4SJiri Olsa NULL, &opts);
838b349efe4SJiri Olsa if (!ASSERT_ERR_PTR(skel->links.test_fentry, "bpf_program__attach_tracing_multi"))
839b349efe4SJiri Olsa goto cleanup;
840b349efe4SJiri Olsa
841b349efe4SJiri Olsa skel->links.test_fexit = bpf_program__attach_tracing_multi(skel->progs.test_fexit,
842b349efe4SJiri Olsa NULL, &opts);
843b349efe4SJiri Olsa if (!ASSERT_ERR_PTR(skel->links.test_fexit, "bpf_program__attach_tracing_multi"))
844b349efe4SJiri Olsa goto cleanup;
845b349efe4SJiri Olsa
846b349efe4SJiri Olsa /* We don't really attach any program, but let's make sure. */
847b349efe4SJiri Olsa tracing_multi_rollback_run(skel);
848b349efe4SJiri Olsa
849b349efe4SJiri Olsa cleanup:
850b349efe4SJiri Olsa tracing_multi_rollback__destroy(skel);
851b349efe4SJiri Olsa free(ids);
852b349efe4SJiri Olsa }
853b349efe4SJiri Olsa
fillers_cleanup(struct tracing_multi_rollback ** skels,int cnt)854b349efe4SJiri Olsa static void fillers_cleanup(struct tracing_multi_rollback **skels, int cnt)
855b349efe4SJiri Olsa {
856b349efe4SJiri Olsa int i;
857b349efe4SJiri Olsa
858b349efe4SJiri Olsa for (i = 0; i < cnt; i++)
859b349efe4SJiri Olsa tracing_multi_rollback__destroy(skels[i]);
860b349efe4SJiri Olsa
861b349efe4SJiri Olsa free(skels);
862b349efe4SJiri Olsa }
863b349efe4SJiri Olsa
extra_load_and_link(void)864b349efe4SJiri Olsa static struct tracing_multi_rollback *extra_load_and_link(void)
865b349efe4SJiri Olsa {
866b349efe4SJiri Olsa struct tracing_multi_rollback *skel;
867b349efe4SJiri Olsa int err;
868b349efe4SJiri Olsa
869b349efe4SJiri Olsa skel = tracing_multi_rollback__open();
870b349efe4SJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi_rollback__open"))
871b349efe4SJiri Olsa goto cleanup;
872b349efe4SJiri Olsa
873b349efe4SJiri Olsa bpf_program__set_autoload(skel->progs.extra, true);
874b349efe4SJiri Olsa
875b349efe4SJiri Olsa err = tracing_multi_rollback__load(skel);
876b349efe4SJiri Olsa if (!ASSERT_OK(err, "tracing_multi_rollback__load"))
877b349efe4SJiri Olsa goto cleanup;
878b349efe4SJiri Olsa
879b349efe4SJiri Olsa skel->links.extra = bpf_program__attach_trace(skel->progs.extra);
880b349efe4SJiri Olsa if (!ASSERT_OK_PTR(skel->links.extra, "bpf_program__attach_trace"))
881b349efe4SJiri Olsa goto cleanup;
882b349efe4SJiri Olsa
883b349efe4SJiri Olsa return skel;
884b349efe4SJiri Olsa
885b349efe4SJiri Olsa cleanup:
886b349efe4SJiri Olsa tracing_multi_rollback__destroy(skel);
887b349efe4SJiri Olsa return NULL;
888b349efe4SJiri Olsa }
889b349efe4SJiri Olsa
fillers_load_and_link(int max)890b349efe4SJiri Olsa static struct tracing_multi_rollback **fillers_load_and_link(int max)
891b349efe4SJiri Olsa {
892b349efe4SJiri Olsa struct tracing_multi_rollback **skels, *skel;
893b349efe4SJiri Olsa int i, err;
894b349efe4SJiri Olsa
895b349efe4SJiri Olsa skels = calloc(max + 1, sizeof(*skels));
896b349efe4SJiri Olsa if (!ASSERT_OK_PTR(skels, "calloc"))
897b349efe4SJiri Olsa return NULL;
898b349efe4SJiri Olsa
899b349efe4SJiri Olsa for (i = 0; i < max; i++) {
900b349efe4SJiri Olsa skel = skels[i] = tracing_multi_rollback__open();
901b349efe4SJiri Olsa if (!ASSERT_OK_PTR(skels[i], "tracing_multi_rollback__open"))
902b349efe4SJiri Olsa goto cleanup;
903b349efe4SJiri Olsa
904b349efe4SJiri Olsa bpf_program__set_autoload(skel->progs.filler, true);
905b349efe4SJiri Olsa
906b349efe4SJiri Olsa err = tracing_multi_rollback__load(skel);
907b349efe4SJiri Olsa if (!ASSERT_OK(err, "tracing_multi_rollback__load"))
908b349efe4SJiri Olsa goto cleanup;
909b349efe4SJiri Olsa
910b349efe4SJiri Olsa skel->links.filler = bpf_program__attach_trace(skel->progs.filler);
911b349efe4SJiri Olsa if (!ASSERT_OK_PTR(skels[i]->links.filler, "bpf_program__attach_trace"))
912b349efe4SJiri Olsa goto cleanup;
913b349efe4SJiri Olsa }
914b349efe4SJiri Olsa
915b349efe4SJiri Olsa return skels;
916b349efe4SJiri Olsa
917b349efe4SJiri Olsa cleanup:
918b349efe4SJiri Olsa fillers_cleanup(skels, i + 1);
919b349efe4SJiri Olsa return NULL;
920b349efe4SJiri Olsa }
921b349efe4SJiri Olsa
test_rollback_unlink(void)922b349efe4SJiri Olsa static void test_rollback_unlink(void)
923b349efe4SJiri Olsa {
924b349efe4SJiri Olsa struct tracing_multi_rollback *skel = NULL, *extra;
925b349efe4SJiri Olsa LIBBPF_OPTS(bpf_tracing_multi_opts, opts);
926b349efe4SJiri Olsa struct tracing_multi_rollback **fillers;
927b349efe4SJiri Olsa size_t cnt = FUNCS_CNT;
928b349efe4SJiri Olsa __u32 *ids = NULL;
929b349efe4SJiri Olsa int err, max;
930b349efe4SJiri Olsa
931b349efe4SJiri Olsa max = get_bpf_max_tramp_links();
932b349efe4SJiri Olsa if (!ASSERT_GE(max, 1, "bpf_max_tramp_links"))
933b349efe4SJiri Olsa return;
934b349efe4SJiri Olsa
935b349efe4SJiri Olsa /* Attach maximum allowed programs to bpf_fentry_test10 */
936b349efe4SJiri Olsa fillers = fillers_load_and_link(max);
937b349efe4SJiri Olsa if (!ASSERT_OK_PTR(fillers, "fillers_load_and_link"))
938b349efe4SJiri Olsa return;
939b349efe4SJiri Olsa
940b349efe4SJiri Olsa extra = extra_load_and_link();
941b349efe4SJiri Olsa if (!ASSERT_OK_PTR(extra, "extra_load_and_link"))
942b349efe4SJiri Olsa goto cleanup;
943b349efe4SJiri Olsa
944b349efe4SJiri Olsa skel = tracing_multi_rollback__open();
945b349efe4SJiri Olsa if (!ASSERT_OK_PTR(skel, "tracing_multi_rollback__open"))
946b349efe4SJiri Olsa goto cleanup;
947b349efe4SJiri Olsa
948b349efe4SJiri Olsa bpf_program__set_autoload(skel->progs.test_fentry, true);
949b349efe4SJiri Olsa bpf_program__set_autoload(skel->progs.test_fexit, true);
950b349efe4SJiri Olsa
951b349efe4SJiri Olsa /*
952b349efe4SJiri Olsa * Attach tracing_multi link on bpf_fentry_test1-10, which will
953b349efe4SJiri Olsa * fail on bpf_fentry_test10 function, because it already has
954b349efe4SJiri Olsa * maximum allowed programs attached.
955b349efe4SJiri Olsa *
956b349efe4SJiri Olsa * The rollback needs to unlink already link-ed trampolines and
957b349efe4SJiri Olsa * put all of them.
958b349efe4SJiri Olsa */
959b349efe4SJiri Olsa err = tracing_multi_rollback__load(skel);
960b349efe4SJiri Olsa if (!ASSERT_OK(err, "tracing_multi_rollback__load"))
961b349efe4SJiri Olsa goto cleanup;
962b349efe4SJiri Olsa
963b349efe4SJiri Olsa ids = get_ids(bpf_fentry_test, cnt, NULL);
964b349efe4SJiri Olsa if (!ASSERT_OK_PTR(ids, "get_ids"))
965b349efe4SJiri Olsa goto cleanup;
966b349efe4SJiri Olsa
967b349efe4SJiri Olsa opts.ids = ids;
968b349efe4SJiri Olsa opts.cnt = cnt;
969b349efe4SJiri Olsa
970b349efe4SJiri Olsa skel->bss->pid = getpid();
971b349efe4SJiri Olsa
972b349efe4SJiri Olsa skel->links.test_fentry = bpf_program__attach_tracing_multi(skel->progs.test_fentry,
973b349efe4SJiri Olsa NULL, &opts);
974b349efe4SJiri Olsa if (!ASSERT_ERR_PTR(skel->links.test_fentry, "bpf_program__attach_tracing_multi"))
975b349efe4SJiri Olsa goto cleanup;
976b349efe4SJiri Olsa
977b349efe4SJiri Olsa skel->links.test_fexit = bpf_program__attach_tracing_multi(skel->progs.test_fexit,
978b349efe4SJiri Olsa NULL, &opts);
979b349efe4SJiri Olsa if (!ASSERT_ERR_PTR(skel->links.test_fexit, "bpf_program__attach_tracing_multi"))
980b349efe4SJiri Olsa goto cleanup;
981b349efe4SJiri Olsa
982b349efe4SJiri Olsa tracing_multi_rollback_run(skel);
983b349efe4SJiri Olsa
984b349efe4SJiri Olsa cleanup:
985b349efe4SJiri Olsa fillers_cleanup(fillers, max);
986b349efe4SJiri Olsa tracing_multi_rollback__destroy(extra);
987b349efe4SJiri Olsa tracing_multi_rollback__destroy(skel);
988b349efe4SJiri Olsa free(ids);
989b349efe4SJiri Olsa }
990b349efe4SJiri Olsa
serial_test_tracing_multi_attach_rollback(void)991b349efe4SJiri Olsa void serial_test_tracing_multi_attach_rollback(void)
992b349efe4SJiri Olsa {
993b349efe4SJiri Olsa if (test__start_subtest("put"))
994b349efe4SJiri Olsa test_rollback_put();
995b349efe4SJiri Olsa if (test__start_subtest("unlink"))
996b349efe4SJiri Olsa test_rollback_unlink();
997b349efe4SJiri Olsa }
998b349efe4SJiri Olsa
test_tracing_multi_test(void)9992922dd58SJiri Olsa void test_tracing_multi_test(void)
10002922dd58SJiri Olsa {
10012922dd58SJiri Olsa #ifndef __x86_64__
10022922dd58SJiri Olsa test__skip();
10032922dd58SJiri Olsa return;
10042922dd58SJiri Olsa #endif
10052922dd58SJiri Olsa
10062922dd58SJiri Olsa if (test__start_subtest("skel_api"))
10072922dd58SJiri Olsa test_skel_api();
10082922dd58SJiri Olsa if (test__start_subtest("link_api_pattern"))
10092922dd58SJiri Olsa test_link_api_pattern();
10102922dd58SJiri Olsa if (test__start_subtest("link_api_ids"))
10111b938f42SJiri Olsa test_link_api_ids(false);
10122863f074SJiri Olsa if (test__start_subtest("module_skel_api"))
10132863f074SJiri Olsa test_module_skel_api();
10142863f074SJiri Olsa if (test__start_subtest("module_link_api_pattern"))
10152863f074SJiri Olsa test_module_link_api_pattern();
10162863f074SJiri Olsa if (test__start_subtest("module_link_api_ids"))
10172863f074SJiri Olsa test_module_link_api_ids();
10184309f580SJiri Olsa if (test__start_subtest("intersect"))
10194309f580SJiri Olsa test_intersect();
10201b938f42SJiri Olsa if (test__start_subtest("cookies"))
10211b938f42SJiri Olsa test_link_api_ids(true);
102269f25d4bSJiri Olsa if (test__start_subtest("session"))
102369f25d4bSJiri Olsa test_session();
10241fd83285SJiri Olsa if (test__start_subtest("attach_api_fails"))
10251fd83285SJiri Olsa test_attach_api_fails();
1026443c91d0SJiri Olsa RUN_TESTS(tracing_multi_verifier);
1027*539d3edfSLeon Hwang if (test__start_subtest("fentry_after_multi"))
1028*539d3edfSLeon Hwang test_fentry_after_multi();
10292922dd58SJiri Olsa }
1030