perf llvm: Allow passing options to llc in addition to clang

The newly added 'llvm.opts' variable allows passing options directly to
llc, like needed to get sane DWARF in BPF ELF debug sections:

With:

  [root@seventh perf]# cat ~/.perfconfig
  [llvm]
	  dump-obj = true
	clang-opt = -g
  [root@seventh perf]#

We get:

  [root@seventh perf]# perf trace -e tools/perf/examples/bpf/hello.c cat /etc/passwd > /dev/null
  LLVM: dumping tools/perf/examples/bpf/hello.o
       0.000 __bpf_stdout__:Hello, world
       0.015 __bpf_stdout__:Hello, world
       0.187 __bpf_stdout__:Hello, world
  [root@seventh perf]# pahole tools/perf/examples/bpf/hello.o
  struct clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566eefef9c3777bd780ec4cbb9efa764633b76c) {
	  clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566e.org clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566eefef9c3777bd780ec4cbb9efa764633b76c); /*     0     4 */
	  clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566e.org clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566eefef9c3777bd780ec4cbb9efa764633b76c); /*     4     4 */
	  clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566e.org clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566eefef9c3777bd780ec4cbb9efa764633b76c); /*     8     4 */
	  clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566e.org clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566eefef9c3777bd780ec4cbb9efa764633b76c); /*    12     4 */
	  clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566e.org clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566eefef9c3777bd780ec4cbb9efa764633b76c); /*    16     4 */
	  clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566e.org clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566eefef9c3777bd780ec4cbb9efa764633b76c); /*    20     4 */
	  clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566e.org clang version 8.0.0 (http://llvm.org/git/clang.git 8587270a739ee30c926a76d5657e65e85b560f6e) (http://llvm.org/git/llvm.git 0566eefef9c3777bd780ec4cbb9efa764633b76c); /*    24     4 */

	  /* size: 28, cachelines: 1, members: 7 */
	  /* last cacheline: 28 bytes */
  };
  [root@seventh perf]#

Adding these options to be passed to llvm's llc:

  [root@seventh perf]# cat ~/.perfconfig
  [llvm]
	  dump-obj = true
	  clang-opt = -g
	  opts = -mattr=dwarfris
  [root@seventh perf]#

We get sane output:

  [root@seventh perf]# perf trace -e tools/perf/examples/bpf/hello.c cat /etc/passwd > /dev/null
  LLVM: dumping tools/perf/examples/bpf/hello.o
       0.000 __bpf_stdout__:Hello, world
       0.015 __bpf_stdout__:Hello, world
       0.185 __bpf_stdout__:Hello, world
  [root@seventh perf]# pahole tools/perf/examples/bpf/hello.o
  struct bpf_map {
	  unsigned int               type;                 /*     0     4 */
	  unsigned int               key_size;             /*     4     4 */
	  unsigned int               value_size;           /*     8     4 */
	  unsigned int               max_entries;          /*    12     4 */
	  unsigned int               map_flags;            /*    16     4 */
	  unsigned int               inner_map_idx;        /*    20     4 */
	  unsigned int               numa_node;            /*    24     4 */

	  /* size: 28, cachelines: 1, members: 7 */
	  /* last cacheline: 28 bytes */
  };
  [root@seventh perf]#

Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Martin KaFai Lau <kafai@fb.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>,
Cc: Yonghong Song <yhs@fb.com>
Link: https://lkml.kernel.org/n/tip-0lrwmrip4dru1651rm8xa7tq@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2018-08-15 17:07:01 -03:00
parent 49836f7811
commit cb76371441
2 changed files with 38 additions and 2 deletions

View File

@ -22,12 +22,14 @@
"$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \ "$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \
"-Wno-unused-value -Wno-pointer-sign " \ "-Wno-unused-value -Wno-pointer-sign " \
"-working-directory $WORKING_DIR " \ "-working-directory $WORKING_DIR " \
"-c \"$CLANG_SOURCE\" -target bpf -O2 -o -" "-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE"
struct llvm_param llvm_param = { struct llvm_param llvm_param = {
.clang_path = "clang", .clang_path = "clang",
.llc_path = "llc",
.clang_bpf_cmd_template = CLANG_BPF_CMD_DEFAULT_TEMPLATE, .clang_bpf_cmd_template = CLANG_BPF_CMD_DEFAULT_TEMPLATE,
.clang_opt = NULL, .clang_opt = NULL,
.opts = NULL,
.kbuild_dir = NULL, .kbuild_dir = NULL,
.kbuild_opts = NULL, .kbuild_opts = NULL,
.user_set_param = false, .user_set_param = false,
@ -51,6 +53,8 @@ int perf_llvm_config(const char *var, const char *value)
llvm_param.kbuild_opts = strdup(value); llvm_param.kbuild_opts = strdup(value);
else if (!strcmp(var, "dump-obj")) else if (!strcmp(var, "dump-obj"))
llvm_param.dump_obj = !!perf_config_bool(var, value); llvm_param.dump_obj = !!perf_config_bool(var, value);
else if (!strcmp(var, "opts"))
llvm_param.opts = strdup(value);
else { else {
pr_debug("Invalid LLVM config option: %s\n", value); pr_debug("Invalid LLVM config option: %s\n", value);
return -1; return -1;
@ -430,11 +434,13 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
unsigned int kernel_version; unsigned int kernel_version;
char linux_version_code_str[64]; char linux_version_code_str[64];
const char *clang_opt = llvm_param.clang_opt; const char *clang_opt = llvm_param.clang_opt;
char clang_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64]; char clang_path[PATH_MAX], llc_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64];
char serr[STRERR_BUFSIZE]; char serr[STRERR_BUFSIZE];
char *kbuild_dir = NULL, *kbuild_include_opts = NULL, char *kbuild_dir = NULL, *kbuild_include_opts = NULL,
*perf_bpf_include_opts = NULL; *perf_bpf_include_opts = NULL;
const char *template = llvm_param.clang_bpf_cmd_template; const char *template = llvm_param.clang_bpf_cmd_template;
char *pipe_template = NULL;
const char *opts = llvm_param.opts;
char *command_echo = NULL, *command_out; char *command_echo = NULL, *command_out;
char *perf_include_dir = system_path(PERF_INCLUDE_DIR); char *perf_include_dir = system_path(PERF_INCLUDE_DIR);
@ -484,6 +490,26 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
force_set_env("PERF_BPF_INC_OPTIONS", perf_bpf_include_opts); force_set_env("PERF_BPF_INC_OPTIONS", perf_bpf_include_opts);
force_set_env("WORKING_DIR", kbuild_dir ? : "."); force_set_env("WORKING_DIR", kbuild_dir ? : ".");
if (opts) {
err = search_program(llvm_param.llc_path, "llc", llc_path);
if (err) {
pr_err("ERROR:\tunable to find llc.\n"
"Hint:\tTry to install latest clang/llvm to support BPF. Check your $PATH\n"
" \tand 'llc-path' option in [llvm] section of ~/.perfconfig.\n");
version_notice();
goto errout;
}
if (asprintf(&pipe_template, "%s -emit-llvm | %s -march=bpf %s -filetype=obj -o -",
template, llc_path, opts) < 0) {
pr_err("ERROR:\tnot enough memory to setup command line\n");
goto errout;
}
template = pipe_template;
}
/* /*
* Since we may reset clang's working dir, path of source file * Since we may reset clang's working dir, path of source file
* should be transferred into absolute path, except we want * should be transferred into absolute path, except we want
@ -535,6 +561,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
free(obj_buf); free(obj_buf);
free(perf_bpf_include_opts); free(perf_bpf_include_opts);
free(perf_include_dir); free(perf_include_dir);
free(pipe_template);
if (p_obj_buf) if (p_obj_buf)
*p_obj_buf = NULL; *p_obj_buf = NULL;
if (p_obj_buf_sz) if (p_obj_buf_sz)

View File

@ -11,6 +11,8 @@
struct llvm_param { struct llvm_param {
/* Path of clang executable */ /* Path of clang executable */
const char *clang_path; const char *clang_path;
/* Path of llc executable */
const char *llc_path;
/* /*
* Template of clang bpf compiling. 5 env variables * Template of clang bpf compiling. 5 env variables
* can be used: * can be used:
@ -23,6 +25,13 @@ struct llvm_param {
const char *clang_bpf_cmd_template; const char *clang_bpf_cmd_template;
/* Will be filled in $CLANG_OPTIONS */ /* Will be filled in $CLANG_OPTIONS */
const char *clang_opt; const char *clang_opt;
/*
* If present it'll add -emit-llvm to $CLANG_OPTIONS to pipe
* the clang output to llc, useful for new llvm options not
* yet selectable via 'clang -mllvm option', such as -mattr=dwarfris
* in clang 6.0/llvm 7
*/
const char *opts;
/* Where to find kbuild system */ /* Where to find kbuild system */
const char *kbuild_dir; const char *kbuild_dir;
/* /*