xref: /OK3568_Linux_fs/kernel/tools/perf/util/llvm-utils.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com>
4*4882a593Smuzhiyun  * Copyright (C) 2015, Huawei Inc.
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <errno.h>
8*4882a593Smuzhiyun #include <limits.h>
9*4882a593Smuzhiyun #include <stdio.h>
10*4882a593Smuzhiyun #include <stdlib.h>
11*4882a593Smuzhiyun #include <unistd.h>
12*4882a593Smuzhiyun #include <linux/err.h>
13*4882a593Smuzhiyun #include <linux/string.h>
14*4882a593Smuzhiyun #include <linux/zalloc.h>
15*4882a593Smuzhiyun #include "debug.h"
16*4882a593Smuzhiyun #include "llvm-utils.h"
17*4882a593Smuzhiyun #include "config.h"
18*4882a593Smuzhiyun #include "util.h"
19*4882a593Smuzhiyun #include <sys/wait.h>
20*4882a593Smuzhiyun #include <subcmd/exec-cmd.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define CLANG_BPF_CMD_DEFAULT_TEMPLATE				\
23*4882a593Smuzhiyun 		"$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
24*4882a593Smuzhiyun 		"-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE "	\
25*4882a593Smuzhiyun 		"$CLANG_OPTIONS $PERF_BPF_INC_OPTIONS $KERNEL_INC_OPTIONS " \
26*4882a593Smuzhiyun 		"-Wno-unused-value -Wno-pointer-sign "		\
27*4882a593Smuzhiyun 		"-working-directory $WORKING_DIR "		\
28*4882a593Smuzhiyun 		"-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE"
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun struct llvm_param llvm_param = {
31*4882a593Smuzhiyun 	.clang_path = "clang",
32*4882a593Smuzhiyun 	.llc_path = "llc",
33*4882a593Smuzhiyun 	.clang_bpf_cmd_template = CLANG_BPF_CMD_DEFAULT_TEMPLATE,
34*4882a593Smuzhiyun 	.clang_opt = NULL,
35*4882a593Smuzhiyun 	.opts = NULL,
36*4882a593Smuzhiyun 	.kbuild_dir = NULL,
37*4882a593Smuzhiyun 	.kbuild_opts = NULL,
38*4882a593Smuzhiyun 	.user_set_param = false,
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun 
perf_llvm_config(const char * var,const char * value)41*4882a593Smuzhiyun int perf_llvm_config(const char *var, const char *value)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	if (!strstarts(var, "llvm."))
44*4882a593Smuzhiyun 		return 0;
45*4882a593Smuzhiyun 	var += sizeof("llvm.") - 1;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	if (!strcmp(var, "clang-path"))
48*4882a593Smuzhiyun 		llvm_param.clang_path = strdup(value);
49*4882a593Smuzhiyun 	else if (!strcmp(var, "clang-bpf-cmd-template"))
50*4882a593Smuzhiyun 		llvm_param.clang_bpf_cmd_template = strdup(value);
51*4882a593Smuzhiyun 	else if (!strcmp(var, "clang-opt"))
52*4882a593Smuzhiyun 		llvm_param.clang_opt = strdup(value);
53*4882a593Smuzhiyun 	else if (!strcmp(var, "kbuild-dir"))
54*4882a593Smuzhiyun 		llvm_param.kbuild_dir = strdup(value);
55*4882a593Smuzhiyun 	else if (!strcmp(var, "kbuild-opts"))
56*4882a593Smuzhiyun 		llvm_param.kbuild_opts = strdup(value);
57*4882a593Smuzhiyun 	else if (!strcmp(var, "dump-obj"))
58*4882a593Smuzhiyun 		llvm_param.dump_obj = !!perf_config_bool(var, value);
59*4882a593Smuzhiyun 	else if (!strcmp(var, "opts"))
60*4882a593Smuzhiyun 		llvm_param.opts = strdup(value);
61*4882a593Smuzhiyun 	else {
62*4882a593Smuzhiyun 		pr_debug("Invalid LLVM config option: %s\n", value);
63*4882a593Smuzhiyun 		return -1;
64*4882a593Smuzhiyun 	}
65*4882a593Smuzhiyun 	llvm_param.user_set_param = true;
66*4882a593Smuzhiyun 	return 0;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun static int
search_program(const char * def,const char * name,char * output)70*4882a593Smuzhiyun search_program(const char *def, const char *name,
71*4882a593Smuzhiyun 	       char *output)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	char *env, *path, *tmp = NULL;
74*4882a593Smuzhiyun 	char buf[PATH_MAX];
75*4882a593Smuzhiyun 	int ret;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	output[0] = '\0';
78*4882a593Smuzhiyun 	if (def && def[0] != '\0') {
79*4882a593Smuzhiyun 		if (def[0] == '/') {
80*4882a593Smuzhiyun 			if (access(def, F_OK) == 0) {
81*4882a593Smuzhiyun 				strlcpy(output, def, PATH_MAX);
82*4882a593Smuzhiyun 				return 0;
83*4882a593Smuzhiyun 			}
84*4882a593Smuzhiyun 		} else if (def[0] != '\0')
85*4882a593Smuzhiyun 			name = def;
86*4882a593Smuzhiyun 	}
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	env = getenv("PATH");
89*4882a593Smuzhiyun 	if (!env)
90*4882a593Smuzhiyun 		return -1;
91*4882a593Smuzhiyun 	env = strdup(env);
92*4882a593Smuzhiyun 	if (!env)
93*4882a593Smuzhiyun 		return -1;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	ret = -ENOENT;
96*4882a593Smuzhiyun 	path = strtok_r(env, ":",  &tmp);
97*4882a593Smuzhiyun 	while (path) {
98*4882a593Smuzhiyun 		scnprintf(buf, sizeof(buf), "%s/%s", path, name);
99*4882a593Smuzhiyun 		if (access(buf, F_OK) == 0) {
100*4882a593Smuzhiyun 			strlcpy(output, buf, PATH_MAX);
101*4882a593Smuzhiyun 			ret = 0;
102*4882a593Smuzhiyun 			break;
103*4882a593Smuzhiyun 		}
104*4882a593Smuzhiyun 		path = strtok_r(NULL, ":", &tmp);
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	free(env);
108*4882a593Smuzhiyun 	return ret;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun #define READ_SIZE	4096
112*4882a593Smuzhiyun static int
read_from_pipe(const char * cmd,void ** p_buf,size_t * p_read_sz)113*4882a593Smuzhiyun read_from_pipe(const char *cmd, void **p_buf, size_t *p_read_sz)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	int err = 0;
116*4882a593Smuzhiyun 	void *buf = NULL;
117*4882a593Smuzhiyun 	FILE *file = NULL;
118*4882a593Smuzhiyun 	size_t read_sz = 0, buf_sz = 0;
119*4882a593Smuzhiyun 	char serr[STRERR_BUFSIZE];
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	file = popen(cmd, "r");
122*4882a593Smuzhiyun 	if (!file) {
123*4882a593Smuzhiyun 		pr_err("ERROR: unable to popen cmd: %s\n",
124*4882a593Smuzhiyun 		       str_error_r(errno, serr, sizeof(serr)));
125*4882a593Smuzhiyun 		return -EINVAL;
126*4882a593Smuzhiyun 	}
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	while (!feof(file) && !ferror(file)) {
129*4882a593Smuzhiyun 		/*
130*4882a593Smuzhiyun 		 * Make buf_sz always have obe byte extra space so we
131*4882a593Smuzhiyun 		 * can put '\0' there.
132*4882a593Smuzhiyun 		 */
133*4882a593Smuzhiyun 		if (buf_sz - read_sz < READ_SIZE + 1) {
134*4882a593Smuzhiyun 			void *new_buf;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 			buf_sz = read_sz + READ_SIZE + 1;
137*4882a593Smuzhiyun 			new_buf = realloc(buf, buf_sz);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 			if (!new_buf) {
140*4882a593Smuzhiyun 				pr_err("ERROR: failed to realloc memory\n");
141*4882a593Smuzhiyun 				err = -ENOMEM;
142*4882a593Smuzhiyun 				goto errout;
143*4882a593Smuzhiyun 			}
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 			buf = new_buf;
146*4882a593Smuzhiyun 		}
147*4882a593Smuzhiyun 		read_sz += fread(buf + read_sz, 1, READ_SIZE, file);
148*4882a593Smuzhiyun 	}
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	if (buf_sz - read_sz < 1) {
151*4882a593Smuzhiyun 		pr_err("ERROR: internal error\n");
152*4882a593Smuzhiyun 		err = -EINVAL;
153*4882a593Smuzhiyun 		goto errout;
154*4882a593Smuzhiyun 	}
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	if (ferror(file)) {
157*4882a593Smuzhiyun 		pr_err("ERROR: error occurred when reading from pipe: %s\n",
158*4882a593Smuzhiyun 		       str_error_r(errno, serr, sizeof(serr)));
159*4882a593Smuzhiyun 		err = -EIO;
160*4882a593Smuzhiyun 		goto errout;
161*4882a593Smuzhiyun 	}
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	err = WEXITSTATUS(pclose(file));
164*4882a593Smuzhiyun 	file = NULL;
165*4882a593Smuzhiyun 	if (err) {
166*4882a593Smuzhiyun 		err = -EINVAL;
167*4882a593Smuzhiyun 		goto errout;
168*4882a593Smuzhiyun 	}
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	/*
171*4882a593Smuzhiyun 	 * If buf is string, give it terminal '\0' to make our life
172*4882a593Smuzhiyun 	 * easier. If buf is not string, that '\0' is out of space
173*4882a593Smuzhiyun 	 * indicated by read_sz so caller won't even notice it.
174*4882a593Smuzhiyun 	 */
175*4882a593Smuzhiyun 	((char *)buf)[read_sz] = '\0';
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	if (!p_buf)
178*4882a593Smuzhiyun 		free(buf);
179*4882a593Smuzhiyun 	else
180*4882a593Smuzhiyun 		*p_buf = buf;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	if (p_read_sz)
183*4882a593Smuzhiyun 		*p_read_sz = read_sz;
184*4882a593Smuzhiyun 	return 0;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun errout:
187*4882a593Smuzhiyun 	if (file)
188*4882a593Smuzhiyun 		pclose(file);
189*4882a593Smuzhiyun 	free(buf);
190*4882a593Smuzhiyun 	if (p_buf)
191*4882a593Smuzhiyun 		*p_buf = NULL;
192*4882a593Smuzhiyun 	if (p_read_sz)
193*4882a593Smuzhiyun 		*p_read_sz = 0;
194*4882a593Smuzhiyun 	return err;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun static inline void
force_set_env(const char * var,const char * value)198*4882a593Smuzhiyun force_set_env(const char *var, const char *value)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun 	if (value) {
201*4882a593Smuzhiyun 		setenv(var, value, 1);
202*4882a593Smuzhiyun 		pr_debug("set env: %s=%s\n", var, value);
203*4882a593Smuzhiyun 	} else {
204*4882a593Smuzhiyun 		unsetenv(var);
205*4882a593Smuzhiyun 		pr_debug("unset env: %s\n", var);
206*4882a593Smuzhiyun 	}
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun static void
version_notice(void)210*4882a593Smuzhiyun version_notice(void)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun 	pr_err(
213*4882a593Smuzhiyun "     \tLLVM 3.7 or newer is required. Which can be found from http://llvm.org\n"
214*4882a593Smuzhiyun "     \tYou may want to try git trunk:\n"
215*4882a593Smuzhiyun "     \t\tgit clone http://llvm.org/git/llvm.git\n"
216*4882a593Smuzhiyun "     \t\t     and\n"
217*4882a593Smuzhiyun "     \t\tgit clone http://llvm.org/git/clang.git\n\n"
218*4882a593Smuzhiyun "     \tOr fetch the latest clang/llvm 3.7 from pre-built llvm packages for\n"
219*4882a593Smuzhiyun "     \tdebian/ubuntu:\n"
220*4882a593Smuzhiyun "     \t\thttp://llvm.org/apt\n\n"
221*4882a593Smuzhiyun "     \tIf you are using old version of clang, change 'clang-bpf-cmd-template'\n"
222*4882a593Smuzhiyun "     \toption in [llvm] section of ~/.perfconfig to:\n\n"
223*4882a593Smuzhiyun "     \t  \"$CLANG_EXEC $CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS \\\n"
224*4882a593Smuzhiyun "     \t     -working-directory $WORKING_DIR -c $CLANG_SOURCE \\\n"
225*4882a593Smuzhiyun "     \t     -emit-llvm -o - | /path/to/llc -march=bpf -filetype=obj -o -\"\n"
226*4882a593Smuzhiyun "     \t(Replace /path/to/llc with path to your llc)\n\n"
227*4882a593Smuzhiyun );
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun 
detect_kbuild_dir(char ** kbuild_dir)230*4882a593Smuzhiyun static int detect_kbuild_dir(char **kbuild_dir)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun 	const char *test_dir = llvm_param.kbuild_dir;
233*4882a593Smuzhiyun 	const char *prefix_dir = "";
234*4882a593Smuzhiyun 	const char *suffix_dir = "";
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	/* _UTSNAME_LENGTH is 65 */
237*4882a593Smuzhiyun 	char release[128];
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	char *autoconf_path;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	int err;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	if (!test_dir) {
244*4882a593Smuzhiyun 		err = fetch_kernel_version(NULL, release,
245*4882a593Smuzhiyun 					   sizeof(release));
246*4882a593Smuzhiyun 		if (err)
247*4882a593Smuzhiyun 			return -EINVAL;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 		test_dir = release;
250*4882a593Smuzhiyun 		prefix_dir = "/lib/modules/";
251*4882a593Smuzhiyun 		suffix_dir = "/build";
252*4882a593Smuzhiyun 	}
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	err = asprintf(&autoconf_path, "%s%s%s/include/generated/autoconf.h",
255*4882a593Smuzhiyun 		       prefix_dir, test_dir, suffix_dir);
256*4882a593Smuzhiyun 	if (err < 0)
257*4882a593Smuzhiyun 		return -ENOMEM;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	if (access(autoconf_path, R_OK) == 0) {
260*4882a593Smuzhiyun 		free(autoconf_path);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 		err = asprintf(kbuild_dir, "%s%s%s", prefix_dir, test_dir,
263*4882a593Smuzhiyun 			       suffix_dir);
264*4882a593Smuzhiyun 		if (err < 0)
265*4882a593Smuzhiyun 			return -ENOMEM;
266*4882a593Smuzhiyun 		return 0;
267*4882a593Smuzhiyun 	}
268*4882a593Smuzhiyun 	pr_debug("%s: Couldn't find \"%s\", missing kernel-devel package?.\n",
269*4882a593Smuzhiyun 		 __func__, autoconf_path);
270*4882a593Smuzhiyun 	free(autoconf_path);
271*4882a593Smuzhiyun 	return -ENOENT;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun static const char *kinc_fetch_script =
275*4882a593Smuzhiyun "#!/usr/bin/env sh\n"
276*4882a593Smuzhiyun "if ! test -d \"$KBUILD_DIR\"\n"
277*4882a593Smuzhiyun "then\n"
278*4882a593Smuzhiyun "	exit 1\n"
279*4882a593Smuzhiyun "fi\n"
280*4882a593Smuzhiyun "if ! test -f \"$KBUILD_DIR/include/generated/autoconf.h\"\n"
281*4882a593Smuzhiyun "then\n"
282*4882a593Smuzhiyun "	exit 1\n"
283*4882a593Smuzhiyun "fi\n"
284*4882a593Smuzhiyun "TMPDIR=`mktemp -d`\n"
285*4882a593Smuzhiyun "if test -z \"$TMPDIR\"\n"
286*4882a593Smuzhiyun "then\n"
287*4882a593Smuzhiyun "    exit 1\n"
288*4882a593Smuzhiyun "fi\n"
289*4882a593Smuzhiyun "cat << EOF > $TMPDIR/Makefile\n"
290*4882a593Smuzhiyun "obj-y := dummy.o\n"
291*4882a593Smuzhiyun "\\$(obj)/%.o: \\$(src)/%.c\n"
292*4882a593Smuzhiyun "\t@echo -n \"\\$(NOSTDINC_FLAGS) \\$(LINUXINCLUDE) \\$(EXTRA_CFLAGS)\"\n"
293*4882a593Smuzhiyun "\t\\$(CC) -c -o \\$@ \\$<\n"
294*4882a593Smuzhiyun "EOF\n"
295*4882a593Smuzhiyun "touch $TMPDIR/dummy.c\n"
296*4882a593Smuzhiyun "make -s -C $KBUILD_DIR M=$TMPDIR $KBUILD_OPTS dummy.o 2>/dev/null\n"
297*4882a593Smuzhiyun "RET=$?\n"
298*4882a593Smuzhiyun "rm -rf $TMPDIR\n"
299*4882a593Smuzhiyun "exit $RET\n";
300*4882a593Smuzhiyun 
llvm__get_kbuild_opts(char ** kbuild_dir,char ** kbuild_include_opts)301*4882a593Smuzhiyun void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun 	static char *saved_kbuild_dir;
304*4882a593Smuzhiyun 	static char *saved_kbuild_include_opts;
305*4882a593Smuzhiyun 	int err;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	if (!kbuild_dir || !kbuild_include_opts)
308*4882a593Smuzhiyun 		return;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	*kbuild_dir = NULL;
311*4882a593Smuzhiyun 	*kbuild_include_opts = NULL;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	if (saved_kbuild_dir && saved_kbuild_include_opts &&
314*4882a593Smuzhiyun 	    !IS_ERR(saved_kbuild_dir) && !IS_ERR(saved_kbuild_include_opts)) {
315*4882a593Smuzhiyun 		*kbuild_dir = strdup(saved_kbuild_dir);
316*4882a593Smuzhiyun 		*kbuild_include_opts = strdup(saved_kbuild_include_opts);
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 		if (*kbuild_dir && *kbuild_include_opts)
319*4882a593Smuzhiyun 			return;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 		zfree(kbuild_dir);
322*4882a593Smuzhiyun 		zfree(kbuild_include_opts);
323*4882a593Smuzhiyun 		/*
324*4882a593Smuzhiyun 		 * Don't fall through: it may breaks saved_kbuild_dir and
325*4882a593Smuzhiyun 		 * saved_kbuild_include_opts if detect them again when
326*4882a593Smuzhiyun 		 * memory is low.
327*4882a593Smuzhiyun 		 */
328*4882a593Smuzhiyun 		return;
329*4882a593Smuzhiyun 	}
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	if (llvm_param.kbuild_dir && !llvm_param.kbuild_dir[0]) {
332*4882a593Smuzhiyun 		pr_debug("[llvm.kbuild-dir] is set to \"\" deliberately.\n");
333*4882a593Smuzhiyun 		pr_debug("Skip kbuild options detection.\n");
334*4882a593Smuzhiyun 		goto errout;
335*4882a593Smuzhiyun 	}
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	err = detect_kbuild_dir(kbuild_dir);
338*4882a593Smuzhiyun 	if (err) {
339*4882a593Smuzhiyun 		pr_warning(
340*4882a593Smuzhiyun "WARNING:\tunable to get correct kernel building directory.\n"
341*4882a593Smuzhiyun "Hint:\tSet correct kbuild directory using 'kbuild-dir' option in [llvm]\n"
342*4882a593Smuzhiyun "     \tsection of ~/.perfconfig or set it to \"\" to suppress kbuild\n"
343*4882a593Smuzhiyun "     \tdetection.\n\n");
344*4882a593Smuzhiyun 		goto errout;
345*4882a593Smuzhiyun 	}
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	pr_debug("Kernel build dir is set to %s\n", *kbuild_dir);
348*4882a593Smuzhiyun 	force_set_env("KBUILD_DIR", *kbuild_dir);
349*4882a593Smuzhiyun 	force_set_env("KBUILD_OPTS", llvm_param.kbuild_opts);
350*4882a593Smuzhiyun 	err = read_from_pipe(kinc_fetch_script,
351*4882a593Smuzhiyun 			     (void **)kbuild_include_opts,
352*4882a593Smuzhiyun 			     NULL);
353*4882a593Smuzhiyun 	if (err) {
354*4882a593Smuzhiyun 		pr_warning(
355*4882a593Smuzhiyun "WARNING:\tunable to get kernel include directories from '%s'\n"
356*4882a593Smuzhiyun "Hint:\tTry set clang include options using 'clang-bpf-cmd-template'\n"
357*4882a593Smuzhiyun "     \toption in [llvm] section of ~/.perfconfig and set 'kbuild-dir'\n"
358*4882a593Smuzhiyun "     \toption in [llvm] to \"\" to suppress this detection.\n\n",
359*4882a593Smuzhiyun 			*kbuild_dir);
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 		zfree(kbuild_dir);
362*4882a593Smuzhiyun 		goto errout;
363*4882a593Smuzhiyun 	}
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	pr_debug("include option is set to %s\n", *kbuild_include_opts);
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	saved_kbuild_dir = strdup(*kbuild_dir);
368*4882a593Smuzhiyun 	saved_kbuild_include_opts = strdup(*kbuild_include_opts);
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	if (!saved_kbuild_dir || !saved_kbuild_include_opts) {
371*4882a593Smuzhiyun 		zfree(&saved_kbuild_dir);
372*4882a593Smuzhiyun 		zfree(&saved_kbuild_include_opts);
373*4882a593Smuzhiyun 	}
374*4882a593Smuzhiyun 	return;
375*4882a593Smuzhiyun errout:
376*4882a593Smuzhiyun 	saved_kbuild_dir = ERR_PTR(-EINVAL);
377*4882a593Smuzhiyun 	saved_kbuild_include_opts = ERR_PTR(-EINVAL);
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
llvm__get_nr_cpus(void)380*4882a593Smuzhiyun int llvm__get_nr_cpus(void)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun 	static int nr_cpus_avail = 0;
383*4882a593Smuzhiyun 	char serr[STRERR_BUFSIZE];
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	if (nr_cpus_avail > 0)
386*4882a593Smuzhiyun 		return nr_cpus_avail;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
389*4882a593Smuzhiyun 	if (nr_cpus_avail <= 0) {
390*4882a593Smuzhiyun 		pr_err(
391*4882a593Smuzhiyun "WARNING:\tunable to get available CPUs in this system: %s\n"
392*4882a593Smuzhiyun "        \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
393*4882a593Smuzhiyun 		nr_cpus_avail = 128;
394*4882a593Smuzhiyun 	}
395*4882a593Smuzhiyun 	return nr_cpus_avail;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun 
llvm__dump_obj(const char * path,void * obj_buf,size_t size)398*4882a593Smuzhiyun void llvm__dump_obj(const char *path, void *obj_buf, size_t size)
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun 	char *obj_path = strdup(path);
401*4882a593Smuzhiyun 	FILE *fp;
402*4882a593Smuzhiyun 	char *p;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	if (!obj_path) {
405*4882a593Smuzhiyun 		pr_warning("WARNING: Not enough memory, skip object dumping\n");
406*4882a593Smuzhiyun 		return;
407*4882a593Smuzhiyun 	}
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	p = strrchr(obj_path, '.');
410*4882a593Smuzhiyun 	if (!p || (strcmp(p, ".c") != 0)) {
411*4882a593Smuzhiyun 		pr_warning("WARNING: invalid llvm source path: '%s', skip object dumping\n",
412*4882a593Smuzhiyun 			   obj_path);
413*4882a593Smuzhiyun 		goto out;
414*4882a593Smuzhiyun 	}
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	p[1] = 'o';
417*4882a593Smuzhiyun 	fp = fopen(obj_path, "wb");
418*4882a593Smuzhiyun 	if (!fp) {
419*4882a593Smuzhiyun 		pr_warning("WARNING: failed to open '%s': %s, skip object dumping\n",
420*4882a593Smuzhiyun 			   obj_path, strerror(errno));
421*4882a593Smuzhiyun 		goto out;
422*4882a593Smuzhiyun 	}
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	pr_debug("LLVM: dumping %s\n", obj_path);
425*4882a593Smuzhiyun 	if (fwrite(obj_buf, size, 1, fp) != 1)
426*4882a593Smuzhiyun 		pr_debug("WARNING: failed to write to file '%s': %s, skip object dumping\n", obj_path, strerror(errno));
427*4882a593Smuzhiyun 	fclose(fp);
428*4882a593Smuzhiyun out:
429*4882a593Smuzhiyun 	free(obj_path);
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun 
llvm__compile_bpf(const char * path,void ** p_obj_buf,size_t * p_obj_buf_sz)432*4882a593Smuzhiyun int llvm__compile_bpf(const char *path, void **p_obj_buf,
433*4882a593Smuzhiyun 		      size_t *p_obj_buf_sz)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun 	size_t obj_buf_sz;
436*4882a593Smuzhiyun 	void *obj_buf = NULL;
437*4882a593Smuzhiyun 	int err, nr_cpus_avail;
438*4882a593Smuzhiyun 	unsigned int kernel_version;
439*4882a593Smuzhiyun 	char linux_version_code_str[64];
440*4882a593Smuzhiyun 	const char *clang_opt = llvm_param.clang_opt;
441*4882a593Smuzhiyun 	char clang_path[PATH_MAX], llc_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64];
442*4882a593Smuzhiyun 	char serr[STRERR_BUFSIZE];
443*4882a593Smuzhiyun 	char *kbuild_dir = NULL, *kbuild_include_opts = NULL,
444*4882a593Smuzhiyun 	     *perf_bpf_include_opts = NULL;
445*4882a593Smuzhiyun 	const char *template = llvm_param.clang_bpf_cmd_template;
446*4882a593Smuzhiyun 	char *pipe_template = NULL;
447*4882a593Smuzhiyun 	const char *opts = llvm_param.opts;
448*4882a593Smuzhiyun 	char *command_echo = NULL, *command_out;
449*4882a593Smuzhiyun 	char *perf_include_dir = system_path(PERF_INCLUDE_DIR);
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	if (path[0] != '-' && realpath(path, abspath) == NULL) {
452*4882a593Smuzhiyun 		err = errno;
453*4882a593Smuzhiyun 		pr_err("ERROR: problems with path %s: %s\n",
454*4882a593Smuzhiyun 		       path, str_error_r(err, serr, sizeof(serr)));
455*4882a593Smuzhiyun 		return -err;
456*4882a593Smuzhiyun 	}
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	if (!template)
459*4882a593Smuzhiyun 		template = CLANG_BPF_CMD_DEFAULT_TEMPLATE;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	err = search_program(llvm_param.clang_path,
462*4882a593Smuzhiyun 			     "clang", clang_path);
463*4882a593Smuzhiyun 	if (err) {
464*4882a593Smuzhiyun 		pr_err(
465*4882a593Smuzhiyun "ERROR:\tunable to find clang.\n"
466*4882a593Smuzhiyun "Hint:\tTry to install latest clang/llvm to support BPF. Check your $PATH\n"
467*4882a593Smuzhiyun "     \tand 'clang-path' option in [llvm] section of ~/.perfconfig.\n");
468*4882a593Smuzhiyun 		version_notice();
469*4882a593Smuzhiyun 		return -ENOENT;
470*4882a593Smuzhiyun 	}
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	/*
473*4882a593Smuzhiyun 	 * This is an optional work. Even it fail we can continue our
474*4882a593Smuzhiyun 	 * work. Needn't to check error return.
475*4882a593Smuzhiyun 	 */
476*4882a593Smuzhiyun 	llvm__get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	nr_cpus_avail = llvm__get_nr_cpus();
479*4882a593Smuzhiyun 	snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d",
480*4882a593Smuzhiyun 		 nr_cpus_avail);
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	if (fetch_kernel_version(&kernel_version, NULL, 0))
483*4882a593Smuzhiyun 		kernel_version = 0;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	snprintf(linux_version_code_str, sizeof(linux_version_code_str),
486*4882a593Smuzhiyun 		 "0x%x", kernel_version);
487*4882a593Smuzhiyun 	if (asprintf(&perf_bpf_include_opts, "-I%s/bpf", perf_include_dir) < 0)
488*4882a593Smuzhiyun 		goto errout;
489*4882a593Smuzhiyun 	force_set_env("NR_CPUS", nr_cpus_avail_str);
490*4882a593Smuzhiyun 	force_set_env("LINUX_VERSION_CODE", linux_version_code_str);
491*4882a593Smuzhiyun 	force_set_env("CLANG_EXEC", clang_path);
492*4882a593Smuzhiyun 	force_set_env("CLANG_OPTIONS", clang_opt);
493*4882a593Smuzhiyun 	force_set_env("KERNEL_INC_OPTIONS", kbuild_include_opts);
494*4882a593Smuzhiyun 	force_set_env("PERF_BPF_INC_OPTIONS", perf_bpf_include_opts);
495*4882a593Smuzhiyun 	force_set_env("WORKING_DIR", kbuild_dir ? : ".");
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	if (opts) {
498*4882a593Smuzhiyun 		err = search_program(llvm_param.llc_path, "llc", llc_path);
499*4882a593Smuzhiyun 		if (err) {
500*4882a593Smuzhiyun 			pr_err("ERROR:\tunable to find llc.\n"
501*4882a593Smuzhiyun 			       "Hint:\tTry to install latest clang/llvm to support BPF. Check your $PATH\n"
502*4882a593Smuzhiyun 			       "     \tand 'llc-path' option in [llvm] section of ~/.perfconfig.\n");
503*4882a593Smuzhiyun 			version_notice();
504*4882a593Smuzhiyun 			goto errout;
505*4882a593Smuzhiyun 		}
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 		err = -ENOMEM;
508*4882a593Smuzhiyun 		if (asprintf(&pipe_template, "%s -emit-llvm | %s -march=bpf %s -filetype=obj -o -",
509*4882a593Smuzhiyun 			      template, llc_path, opts) < 0) {
510*4882a593Smuzhiyun 			pr_err("ERROR:\tnot enough memory to setup command line\n");
511*4882a593Smuzhiyun 			goto errout;
512*4882a593Smuzhiyun 		}
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 		template = pipe_template;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	}
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	/*
519*4882a593Smuzhiyun 	 * Since we may reset clang's working dir, path of source file
520*4882a593Smuzhiyun 	 * should be transferred into absolute path, except we want
521*4882a593Smuzhiyun 	 * stdin to be source file (testing).
522*4882a593Smuzhiyun 	 */
523*4882a593Smuzhiyun 	force_set_env("CLANG_SOURCE",
524*4882a593Smuzhiyun 		      (path[0] == '-') ? path : abspath);
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	pr_debug("llvm compiling command template: %s\n", template);
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	err = -ENOMEM;
529*4882a593Smuzhiyun 	if (asprintf(&command_echo, "echo -n \"%s\"", template) < 0)
530*4882a593Smuzhiyun 		goto errout;
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	err = read_from_pipe(command_echo, (void **) &command_out, NULL);
533*4882a593Smuzhiyun 	if (err)
534*4882a593Smuzhiyun 		goto errout;
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	pr_debug("llvm compiling command : %s\n", command_out);
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	err = read_from_pipe(template, &obj_buf, &obj_buf_sz);
539*4882a593Smuzhiyun 	if (err) {
540*4882a593Smuzhiyun 		pr_err("ERROR:\tunable to compile %s\n", path);
541*4882a593Smuzhiyun 		pr_err("Hint:\tCheck error message shown above.\n");
542*4882a593Smuzhiyun 		pr_err("Hint:\tYou can also pre-compile it into .o using:\n");
543*4882a593Smuzhiyun 		pr_err("     \t\tclang -target bpf -O2 -c %s\n", path);
544*4882a593Smuzhiyun 		pr_err("     \twith proper -I and -D options.\n");
545*4882a593Smuzhiyun 		goto errout;
546*4882a593Smuzhiyun 	}
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	free(command_echo);
549*4882a593Smuzhiyun 	free(command_out);
550*4882a593Smuzhiyun 	free(kbuild_dir);
551*4882a593Smuzhiyun 	free(kbuild_include_opts);
552*4882a593Smuzhiyun 	free(perf_bpf_include_opts);
553*4882a593Smuzhiyun 	free(perf_include_dir);
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 	if (!p_obj_buf)
556*4882a593Smuzhiyun 		free(obj_buf);
557*4882a593Smuzhiyun 	else
558*4882a593Smuzhiyun 		*p_obj_buf = obj_buf;
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	if (p_obj_buf_sz)
561*4882a593Smuzhiyun 		*p_obj_buf_sz = obj_buf_sz;
562*4882a593Smuzhiyun 	return 0;
563*4882a593Smuzhiyun errout:
564*4882a593Smuzhiyun 	free(command_echo);
565*4882a593Smuzhiyun 	free(kbuild_dir);
566*4882a593Smuzhiyun 	free(kbuild_include_opts);
567*4882a593Smuzhiyun 	free(obj_buf);
568*4882a593Smuzhiyun 	free(perf_bpf_include_opts);
569*4882a593Smuzhiyun 	free(perf_include_dir);
570*4882a593Smuzhiyun 	free(pipe_template);
571*4882a593Smuzhiyun 	if (p_obj_buf)
572*4882a593Smuzhiyun 		*p_obj_buf = NULL;
573*4882a593Smuzhiyun 	if (p_obj_buf_sz)
574*4882a593Smuzhiyun 		*p_obj_buf_sz = 0;
575*4882a593Smuzhiyun 	return err;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun 
llvm__search_clang(void)578*4882a593Smuzhiyun int llvm__search_clang(void)
579*4882a593Smuzhiyun {
580*4882a593Smuzhiyun 	char clang_path[PATH_MAX];
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	return search_program(llvm_param.clang_path, "clang", clang_path);
583*4882a593Smuzhiyun }
584