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