0001
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
0070
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
0080
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
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 };