Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <stdio.h>
0003 #include <stdlib.h>
0004 #include <string.h>
0005 #include "tests.h"
0006 #include "debug.h"
0007 
0008 #ifdef HAVE_LIBBPF_SUPPORT
0009 #include <bpf/libbpf.h>
0010 #include <util/llvm-utils.h>
0011 #include "llvm.h"
0012 static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
0013 {
0014     struct bpf_object *obj;
0015 
0016     obj = bpf_object__open_mem(obj_buf, obj_buf_sz, NULL);
0017     if (libbpf_get_error(obj))
0018         return TEST_FAIL;
0019     bpf_object__close(obj);
0020     return TEST_OK;
0021 }
0022 
0023 static struct {
0024     const char *source;
0025     const char *desc;
0026     bool should_load_fail;
0027 } bpf_source_table[__LLVM_TESTCASE_MAX] = {
0028     [LLVM_TESTCASE_BASE] = {
0029         .source = test_llvm__bpf_base_prog,
0030         .desc = "Basic BPF llvm compile",
0031     },
0032     [LLVM_TESTCASE_KBUILD] = {
0033         .source = test_llvm__bpf_test_kbuild_prog,
0034         .desc = "kbuild searching",
0035     },
0036     [LLVM_TESTCASE_BPF_PROLOGUE] = {
0037         .source = test_llvm__bpf_test_prologue_prog,
0038         .desc = "Compile source for BPF prologue generation",
0039     },
0040     [LLVM_TESTCASE_BPF_RELOCATION] = {
0041         .source = test_llvm__bpf_test_relocation,
0042         .desc = "Compile source for BPF relocation",
0043         .should_load_fail = true,
0044     },
0045 };
0046 
0047 int
0048 test_llvm__fetch_bpf_obj(void **p_obj_buf,
0049              size_t *p_obj_buf_sz,
0050              enum test_llvm__testcase idx,
0051              bool force,
0052              bool *should_load_fail)
0053 {
0054     const char *source;
0055     const char *desc;
0056     const char *tmpl_old, *clang_opt_old;
0057     char *tmpl_new = NULL, *clang_opt_new = NULL;
0058     int err, old_verbose, ret = TEST_FAIL;
0059 
0060     if (idx >= __LLVM_TESTCASE_MAX)
0061         return TEST_FAIL;
0062 
0063     source = bpf_source_table[idx].source;
0064     desc = bpf_source_table[idx].desc;
0065     if (should_load_fail)
0066         *should_load_fail = bpf_source_table[idx].should_load_fail;
0067 
0068     /*
0069      * Skip this test if user's .perfconfig doesn't set [llvm] section
0070      * and clang is not found in $PATH
0071      */
0072     if (!force && (!llvm_param.user_set_param &&
0073                llvm__search_clang())) {
0074         pr_debug("No clang, skip this test\n");
0075         return TEST_SKIP;
0076     }
0077 
0078     /*
0079      * llvm is verbosity when error. Suppress all error output if
0080      * not 'perf test -v'.
0081      */
0082     old_verbose = verbose;
0083     if (verbose == 0)
0084         verbose = -1;
0085 
0086     *p_obj_buf = NULL;
0087     *p_obj_buf_sz = 0;
0088 
0089     if (!llvm_param.clang_bpf_cmd_template)
0090         goto out;
0091 
0092     if (!llvm_param.clang_opt)
0093         llvm_param.clang_opt = strdup("");
0094 
0095     err = asprintf(&tmpl_new, "echo '%s' | %s%s", source,
0096                llvm_param.clang_bpf_cmd_template,
0097                old_verbose ? "" : " 2>/dev/null");
0098     if (err < 0)
0099         goto out;
0100     err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt);
0101     if (err < 0)
0102         goto out;
0103 
0104     tmpl_old = llvm_param.clang_bpf_cmd_template;
0105     llvm_param.clang_bpf_cmd_template = tmpl_new;
0106     clang_opt_old = llvm_param.clang_opt;
0107     llvm_param.clang_opt = clang_opt_new;
0108 
0109     err = llvm__compile_bpf("-", p_obj_buf, p_obj_buf_sz);
0110 
0111     llvm_param.clang_bpf_cmd_template = tmpl_old;
0112     llvm_param.clang_opt = clang_opt_old;
0113 
0114     verbose = old_verbose;
0115     if (err)
0116         goto out;
0117 
0118     ret = TEST_OK;
0119 out:
0120     free(tmpl_new);
0121     free(clang_opt_new);
0122     if (ret != TEST_OK)
0123         pr_debug("Failed to compile test case: '%s'\n", desc);
0124     return ret;
0125 }
0126 
0127 static int test__llvm(int subtest)
0128 {
0129     int ret;
0130     void *obj_buf = NULL;
0131     size_t obj_buf_sz = 0;
0132     bool should_load_fail = false;
0133 
0134     if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
0135         return TEST_FAIL;
0136 
0137     ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
0138                        subtest, false, &should_load_fail);
0139 
0140     if (ret == TEST_OK && !should_load_fail) {
0141         ret = test__bpf_parsing(obj_buf, obj_buf_sz);
0142         if (ret != TEST_OK) {
0143             pr_debug("Failed to parse test case '%s'\n",
0144                  bpf_source_table[subtest].desc);
0145         }
0146     }
0147     free(obj_buf);
0148 
0149     return ret;
0150 }
0151 #endif //HAVE_LIBBPF_SUPPORT
0152 
0153 static int test__llvm__bpf_base_prog(struct test_suite *test __maybe_unused,
0154                      int subtest __maybe_unused)
0155 {
0156 #ifdef HAVE_LIBBPF_SUPPORT
0157     return test__llvm(LLVM_TESTCASE_BASE);
0158 #else
0159     pr_debug("Skip LLVM test because BPF support is not compiled\n");
0160     return TEST_SKIP;
0161 #endif
0162 }
0163 
0164 static int test__llvm__bpf_test_kbuild_prog(struct test_suite *test __maybe_unused,
0165                         int subtest __maybe_unused)
0166 {
0167 #ifdef HAVE_LIBBPF_SUPPORT
0168     return test__llvm(LLVM_TESTCASE_KBUILD);
0169 #else
0170     pr_debug("Skip LLVM test because BPF support is not compiled\n");
0171     return TEST_SKIP;
0172 #endif
0173 }
0174 
0175 static int test__llvm__bpf_test_prologue_prog(struct test_suite *test __maybe_unused,
0176                           int subtest __maybe_unused)
0177 {
0178 #ifdef HAVE_LIBBPF_SUPPORT
0179     return test__llvm(LLVM_TESTCASE_BPF_PROLOGUE);
0180 #else
0181     pr_debug("Skip LLVM test because BPF support is not compiled\n");
0182     return TEST_SKIP;
0183 #endif
0184 }
0185 
0186 static int test__llvm__bpf_test_relocation(struct test_suite *test __maybe_unused,
0187                        int subtest __maybe_unused)
0188 {
0189 #ifdef HAVE_LIBBPF_SUPPORT
0190     return test__llvm(LLVM_TESTCASE_BPF_RELOCATION);
0191 #else
0192     pr_debug("Skip LLVM test because BPF support is not compiled\n");
0193     return TEST_SKIP;
0194 #endif
0195 }
0196 
0197 
0198 static struct test_case llvm_tests[] = {
0199 #ifdef HAVE_LIBBPF_SUPPORT
0200     TEST_CASE("Basic BPF llvm compile", llvm__bpf_base_prog),
0201     TEST_CASE("kbuild searching", llvm__bpf_test_kbuild_prog),
0202     TEST_CASE("Compile source for BPF prologue generation",
0203           llvm__bpf_test_prologue_prog),
0204     TEST_CASE("Compile source for BPF relocation", llvm__bpf_test_relocation),
0205 #else
0206     TEST_CASE_REASON("Basic BPF llvm compile", llvm__bpf_base_prog, "not compiled in"),
0207     TEST_CASE_REASON("kbuild searching", llvm__bpf_test_kbuild_prog, "not compiled in"),
0208     TEST_CASE_REASON("Compile source for BPF prologue generation",
0209             llvm__bpf_test_prologue_prog, "not compiled in"),
0210     TEST_CASE_REASON("Compile source for BPF relocation",
0211             llvm__bpf_test_relocation, "not compiled in"),
0212 #endif
0213     { .name = NULL, }
0214 };
0215 
0216 struct test_suite suite__llvm = {
0217     .desc = "LLVM search and compile",
0218     .test_cases = llvm_tests,
0219 };