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