Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  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_buffer(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, and this is not perf test -v
 71	 */
 72	if (!force && (verbose <= 0 &&
 73		       !llvm_param.user_set_param &&
 74		       llvm__search_clang())) {
 75		pr_debug("No clang and no verbosive, skip this test\n");
 76		return TEST_SKIP;
 77	}
 78
 79	/*
 80	 * llvm is verbosity when error. Suppress all error output if
 81	 * not 'perf test -v'.
 82	 */
 83	old_verbose = verbose;
 84	if (verbose == 0)
 85		verbose = -1;
 86
 87	*p_obj_buf = NULL;
 88	*p_obj_buf_sz = 0;
 89
 90	if (!llvm_param.clang_bpf_cmd_template)
 91		goto out;
 92
 93	if (!llvm_param.clang_opt)
 94		llvm_param.clang_opt = strdup("");
 95
 96	err = asprintf(&tmpl_new, "echo '%s' | %s%s", source,
 97		       llvm_param.clang_bpf_cmd_template,
 98		       old_verbose ? "" : " 2>/dev/null");
 99	if (err < 0)
100		goto out;
101	err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt);
102	if (err < 0)
103		goto out;
104
105	tmpl_old = llvm_param.clang_bpf_cmd_template;
106	llvm_param.clang_bpf_cmd_template = tmpl_new;
107	clang_opt_old = llvm_param.clang_opt;
108	llvm_param.clang_opt = clang_opt_new;
109
110	err = llvm__compile_bpf("-", p_obj_buf, p_obj_buf_sz);
111
112	llvm_param.clang_bpf_cmd_template = tmpl_old;
113	llvm_param.clang_opt = clang_opt_old;
114
115	verbose = old_verbose;
116	if (err)
117		goto out;
118
119	ret = TEST_OK;
120out:
121	free(tmpl_new);
122	free(clang_opt_new);
123	if (ret != TEST_OK)
124		pr_debug("Failed to compile test case: '%s'\n", desc);
125	return ret;
126}
127
128int test__llvm(struct test *test __maybe_unused, int subtest)
129{
130	int ret;
131	void *obj_buf = NULL;
132	size_t obj_buf_sz = 0;
133	bool should_load_fail = false;
134
135	if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
136		return TEST_FAIL;
137
138	ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
139				       subtest, false, &should_load_fail);
140
141	if (ret == TEST_OK && !should_load_fail) {
142		ret = test__bpf_parsing(obj_buf, obj_buf_sz);
143		if (ret != TEST_OK) {
144			pr_debug("Failed to parse test case '%s'\n",
145				 bpf_source_table[subtest].desc);
146		}
147	}
148	free(obj_buf);
149
150	return ret;
151}
152
153int test__llvm_subtest_get_nr(void)
154{
155	return __LLVM_TESTCASE_MAX;
156}
157
158const char *test__llvm_subtest_get_desc(int subtest)
159{
160	if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
161		return NULL;
162
163	return bpf_source_table[subtest].desc;
164}
165#else //HAVE_LIBBPF_SUPPORT
166int test__llvm(struct test *test __maybe_unused, int subtest __maybe_unused)
167{
168	return TEST_SKIP;
169}
170
171int test__llvm_subtest_get_nr(void)
172{
173	return 0;
174}
175
176const char *test__llvm_subtest_get_desc(int subtest __maybe_unused)
177{
178	return NULL;
179}
180#endif // HAVE_LIBBPF_SUPPORT