• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
test__bpf_parsing(void * obj_buf,size_t obj_buf_sz)11 static 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
test__bpf_parsing(void * obj_buf __maybe_unused,size_t obj_buf_sz __maybe_unused)22 static 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 
30 static 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 
54 int
test_llvm__fetch_bpf_obj(void ** p_obj_buf,size_t * p_obj_buf_sz,enum test_llvm__testcase idx,bool force,bool * should_load_fail)55 test_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;
127 out:
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 
test__llvm(int subtest)135 int 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 
test__llvm_subtest_get_nr(void)160 int test__llvm_subtest_get_nr(void)
161 {
162 	return __LLVM_TESTCASE_MAX;
163 }
164 
test__llvm_subtest_get_desc(int subtest)165 const 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 }
172