llvm.c (5649B)
1// SPDX-License-Identifier: GPL-2.0 2#include <stdio.h> 3#include <stdlib.h> 4#include <string.h> 5#include "tests.h" 6#include "debug.h" 7 8#ifdef HAVE_LIBBPF_SUPPORT 9#include <bpf/libbpf.h> 10#include <util/llvm-utils.h> 11#include "llvm.h" 12static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz) 13{ 14 struct bpf_object *obj; 15 16 obj = bpf_object__open_mem(obj_buf, obj_buf_sz, NULL); 17 if (libbpf_get_error(obj)) 18 return TEST_FAIL; 19 bpf_object__close(obj); 20 return TEST_OK; 21} 22 23static struct { 24 const char *source; 25 const char *desc; 26 bool should_load_fail; 27} bpf_source_table[__LLVM_TESTCASE_MAX] = { 28 [LLVM_TESTCASE_BASE] = { 29 .source = test_llvm__bpf_base_prog, 30 .desc = "Basic BPF llvm compile", 31 }, 32 [LLVM_TESTCASE_KBUILD] = { 33 .source = test_llvm__bpf_test_kbuild_prog, 34 .desc = "kbuild searching", 35 }, 36 [LLVM_TESTCASE_BPF_PROLOGUE] = { 37 .source = test_llvm__bpf_test_prologue_prog, 38 .desc = "Compile source for BPF prologue generation", 39 }, 40 [LLVM_TESTCASE_BPF_RELOCATION] = { 41 .source = test_llvm__bpf_test_relocation, 42 .desc = "Compile source for BPF relocation", 43 .should_load_fail = true, 44 }, 45}; 46 47int 48test_llvm__fetch_bpf_obj(void **p_obj_buf, 49 size_t *p_obj_buf_sz, 50 enum test_llvm__testcase idx, 51 bool force, 52 bool *should_load_fail) 53{ 54 const char *source; 55 const char *desc; 56 const char *tmpl_old, *clang_opt_old; 57 char *tmpl_new = NULL, *clang_opt_new = NULL; 58 int err, old_verbose, ret = TEST_FAIL; 59 60 if (idx >= __LLVM_TESTCASE_MAX) 61 return TEST_FAIL; 62 63 source = bpf_source_table[idx].source; 64 desc = bpf_source_table[idx].desc; 65 if (should_load_fail) 66 *should_load_fail = bpf_source_table[idx].should_load_fail; 67 68 /* 69 * Skip this test if user's .perfconfig doesn't set [llvm] section 70 * and clang is not found in $PATH 71 */ 72 if (!force && (!llvm_param.user_set_param && 73 llvm__search_clang())) { 74 pr_debug("No clang, skip this test\n"); 75 return TEST_SKIP; 76 } 77 78 /* 79 * llvm is verbosity when error. Suppress all error output if 80 * not 'perf test -v'. 81 */ 82 old_verbose = verbose; 83 if (verbose == 0) 84 verbose = -1; 85 86 *p_obj_buf = NULL; 87 *p_obj_buf_sz = 0; 88 89 if (!llvm_param.clang_bpf_cmd_template) 90 goto out; 91 92 if (!llvm_param.clang_opt) 93 llvm_param.clang_opt = strdup(""); 94 95 err = asprintf(&tmpl_new, "echo '%s' | %s%s", source, 96 llvm_param.clang_bpf_cmd_template, 97 old_verbose ? "" : " 2>/dev/null"); 98 if (err < 0) 99 goto out; 100 err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt); 101 if (err < 0) 102 goto out; 103 104 tmpl_old = llvm_param.clang_bpf_cmd_template; 105 llvm_param.clang_bpf_cmd_template = tmpl_new; 106 clang_opt_old = llvm_param.clang_opt; 107 llvm_param.clang_opt = clang_opt_new; 108 109 err = llvm__compile_bpf("-", p_obj_buf, p_obj_buf_sz); 110 111 llvm_param.clang_bpf_cmd_template = tmpl_old; 112 llvm_param.clang_opt = clang_opt_old; 113 114 verbose = old_verbose; 115 if (err) 116 goto out; 117 118 ret = TEST_OK; 119out: 120 free(tmpl_new); 121 free(clang_opt_new); 122 if (ret != TEST_OK) 123 pr_debug("Failed to compile test case: '%s'\n", desc); 124 return ret; 125} 126 127static int test__llvm(int subtest) 128{ 129 int ret; 130 void *obj_buf = NULL; 131 size_t obj_buf_sz = 0; 132 bool should_load_fail = false; 133 134 if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX)) 135 return TEST_FAIL; 136 137 ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz, 138 subtest, false, &should_load_fail); 139 140 if (ret == TEST_OK && !should_load_fail) { 141 ret = test__bpf_parsing(obj_buf, obj_buf_sz); 142 if (ret != TEST_OK) { 143 pr_debug("Failed to parse test case '%s'\n", 144 bpf_source_table[subtest].desc); 145 } 146 } 147 free(obj_buf); 148 149 return ret; 150} 151#endif //HAVE_LIBBPF_SUPPORT 152 153static int test__llvm__bpf_base_prog(struct test_suite *test __maybe_unused, 154 int subtest __maybe_unused) 155{ 156#ifdef HAVE_LIBBPF_SUPPORT 157 return test__llvm(LLVM_TESTCASE_BASE); 158#else 159 pr_debug("Skip LLVM test because BPF support is not compiled\n"); 160 return TEST_SKIP; 161#endif 162} 163 164static int test__llvm__bpf_test_kbuild_prog(struct test_suite *test __maybe_unused, 165 int subtest __maybe_unused) 166{ 167#ifdef HAVE_LIBBPF_SUPPORT 168 return test__llvm(LLVM_TESTCASE_KBUILD); 169#else 170 pr_debug("Skip LLVM test because BPF support is not compiled\n"); 171 return TEST_SKIP; 172#endif 173} 174 175static int test__llvm__bpf_test_prologue_prog(struct test_suite *test __maybe_unused, 176 int subtest __maybe_unused) 177{ 178#ifdef HAVE_LIBBPF_SUPPORT 179 return test__llvm(LLVM_TESTCASE_BPF_PROLOGUE); 180#else 181 pr_debug("Skip LLVM test because BPF support is not compiled\n"); 182 return TEST_SKIP; 183#endif 184} 185 186static int test__llvm__bpf_test_relocation(struct test_suite *test __maybe_unused, 187 int subtest __maybe_unused) 188{ 189#ifdef HAVE_LIBBPF_SUPPORT 190 return test__llvm(LLVM_TESTCASE_BPF_RELOCATION); 191#else 192 pr_debug("Skip LLVM test because BPF support is not compiled\n"); 193 return TEST_SKIP; 194#endif 195} 196 197 198static struct test_case llvm_tests[] = { 199#ifdef HAVE_LIBBPF_SUPPORT 200 TEST_CASE("Basic BPF llvm compile", llvm__bpf_base_prog), 201 TEST_CASE("kbuild searching", llvm__bpf_test_kbuild_prog), 202 TEST_CASE("Compile source for BPF prologue generation", 203 llvm__bpf_test_prologue_prog), 204 TEST_CASE("Compile source for BPF relocation", llvm__bpf_test_relocation), 205#else 206 TEST_CASE_REASON("Basic BPF llvm compile", llvm__bpf_base_prog, "not compiled in"), 207 TEST_CASE_REASON("kbuild searching", llvm__bpf_test_kbuild_prog, "not compiled in"), 208 TEST_CASE_REASON("Compile source for BPF prologue generation", 209 llvm__bpf_test_prologue_prog, "not compiled in"), 210 TEST_CASE_REASON("Compile source for BPF relocation", 211 llvm__bpf_test_relocation, "not compiled in"), 212#endif 213 { .name = NULL, } 214}; 215 216struct test_suite suite__llvm = { 217 .desc = "LLVM search and compile", 218 .test_cases = llvm_tests, 219};