1#include <stdio.h> 2#include <bpf/libbpf.h> 3#include <util/llvm-utils.h> 4#include <util/cache.h> 5#include "llvm.h" 6#include "tests.h" 7#include "debug.h" 8 9static int perf_config_cb(const char *var, const char *val, 10 void *arg __maybe_unused) 11{ 12 return perf_default_config(var, val, arg); 13} 14 15#ifdef HAVE_LIBBPF_SUPPORT 16static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz) 17{ 18 struct bpf_object *obj; 19 20 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL); 21 if (IS_ERR(obj)) 22 return TEST_FAIL; 23 bpf_object__close(obj); 24 return TEST_OK; 25} 26#else 27static int test__bpf_parsing(void *obj_buf __maybe_unused, 28 size_t obj_buf_sz __maybe_unused) 29{ 30 pr_debug("Skip bpf parsing\n"); 31 return TEST_OK; 32} 33#endif 34 35static struct { 36 const char *source; 37 const char *desc; 38} bpf_source_table[__LLVM_TESTCASE_MAX] = { 39 [LLVM_TESTCASE_BASE] = { 40 .source = test_llvm__bpf_base_prog, 41 .desc = "Basic BPF llvm compiling test", 42 }, 43 [LLVM_TESTCASE_KBUILD] = { 44 .source = test_llvm__bpf_test_kbuild_prog, 45 .desc = "Test kbuild searching", 46 }, 47}; 48 49 50int 51test_llvm__fetch_bpf_obj(void **p_obj_buf, 52 size_t *p_obj_buf_sz, 53 enum test_llvm__testcase idx, 54 bool force) 55{ 56 const char *source; 57 const char *desc; 58 const char *tmpl_old, *clang_opt_old; 59 char *tmpl_new = NULL, *clang_opt_new = NULL; 60 int err, old_verbose, ret = TEST_FAIL; 61 62 if (idx >= __LLVM_TESTCASE_MAX) 63 return TEST_FAIL; 64 65 source = bpf_source_table[idx].source; 66 desc = bpf_source_table[idx].desc; 67 68 perf_config(perf_config_cb, NULL); 69 70 /* 71 * Skip this test if user's .perfconfig doesn't set [llvm] section 72 * and clang is not found in $PATH, and this is not perf test -v 73 */ 74 if (!force && (verbose == 0 && 75 !llvm_param.user_set_param && 76 llvm__search_clang())) { 77 pr_debug("No clang and no verbosive, skip this test\n"); 78 return TEST_SKIP; 79 } 80 81 /* 82 * llvm is verbosity when error. Suppress all error output if 83 * not 'perf test -v'. 84 */ 85 old_verbose = verbose; 86 if (verbose == 0) 87 verbose = -1; 88 89 *p_obj_buf = NULL; 90 *p_obj_buf_sz = 0; 91 92 if (!llvm_param.clang_bpf_cmd_template) 93 goto out; 94 95 if (!llvm_param.clang_opt) 96 llvm_param.clang_opt = strdup(""); 97 98 err = asprintf(&tmpl_new, "echo '%s' | %s%s", source, 99 llvm_param.clang_bpf_cmd_template, 100 old_verbose ? "" : " 2>/dev/null"); 101 if (err < 0) 102 goto out; 103 err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt); 104 if (err < 0) 105 goto out; 106 107 tmpl_old = llvm_param.clang_bpf_cmd_template; 108 llvm_param.clang_bpf_cmd_template = tmpl_new; 109 clang_opt_old = llvm_param.clang_opt; 110 llvm_param.clang_opt = clang_opt_new; 111 112 err = llvm__compile_bpf("-", p_obj_buf, p_obj_buf_sz); 113 114 llvm_param.clang_bpf_cmd_template = tmpl_old; 115 llvm_param.clang_opt = clang_opt_old; 116 117 verbose = old_verbose; 118 if (err) 119 goto out; 120 121 ret = TEST_OK; 122out: 123 free(tmpl_new); 124 free(clang_opt_new); 125 if (ret != TEST_OK) 126 pr_debug("Failed to compile test case: '%s'\n", desc); 127 return ret; 128} 129 130int test__llvm(void) 131{ 132 enum test_llvm__testcase i; 133 134 for (i = 0; i < __LLVM_TESTCASE_MAX; i++) { 135 int ret; 136 void *obj_buf = NULL; 137 size_t obj_buf_sz = 0; 138 139 ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz, 140 i, false); 141 142 if (ret == TEST_OK) { 143 ret = test__bpf_parsing(obj_buf, obj_buf_sz); 144 if (ret != TEST_OK) 145 pr_debug("Failed to parse test case '%s'\n", 146 bpf_source_table[i].desc); 147 } 148 free(obj_buf); 149 150 switch (ret) { 151 case TEST_SKIP: 152 return TEST_SKIP; 153 case TEST_OK: 154 break; 155 default: 156 /* 157 * Test 0 is the basic LLVM test. If test 0 158 * fail, the basic LLVM support not functional 159 * so the whole test should fail. If other test 160 * case fail, it can be fixed by adjusting 161 * config so don't report error. 162 */ 163 if (i == 0) 164 return TEST_FAIL; 165 else 166 return TEST_SKIP; 167 } 168 } 169 return TEST_OK; 170} 171