[tip:perf/core] perf llvm: Allow dump llvm output object file using llvm.dump-obj

2016-06-22 Thread tip-bot for Wang Nan
Commit-ID:  f078464925f5b5c977c1196c67cae49cd82f40ff
Gitweb: http://git.kernel.org/tip/f078464925f5b5c977c1196c67cae49cd82f40ff
Author: Wang Nan 
AuthorDate: Thu, 16 Jun 2016 08:02:40 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 21 Jun 2016 13:18:34 -0300

perf llvm: Allow dump llvm output object file using llvm.dump-obj

Add a 'llvm.dump-obj' config option to enable perf dump BPF object files
compiled by LLVM.

This option is useful when using BPF objects in embedded platforms.
LLVM compiler won't be deployed in these platforms, and currently we
don't support dynamic compiling library.

Before this patch users have to explicitly issue llvm commands to
compile BPF scripts, and can't use helpers (like include path detection
and default macros) in perf. With this option, user is allowed to use
perf to compile their BPF objects then copy them into their embedded
platforms.

Committer notice:

Testing it:

  # cat ~/.perfconfig
  [llvm]
dump-obj = true
  #
  # ls -la filter.o
  ls: cannot access filter.o: No such file or directory
  # cat filter.c
  #include 
  #define SEC(NAME) __attribute__((section(NAME), used))

  SEC("func=hrtimer_nanosleep rqtp->tv_nsec")
  int func(void *ctx, int err, long nsec)
  {
return nsec > 1000;
  }
  char _license[] SEC("license") = "GPL";
  int _version SEC("version") = LINUX_VERSION_CODE;
  # trace -e nanosleep --event filter.c usleep 6
  LLVM: dumping filter.o
 0.007 ( 0.007 ms): usleep/13976 nanosleep(rqtp: 0x7ffc5847f640 
   ) ...
 0.007 ( ): perf_bpf_probe:func:(811137d0) tv_nsec=6000)
 0.070 ( 0.070 ms): usleep/13976  ... [continued]: nanosleep()) = 0
  # ls -la filter.o
  -rw-r--r--. 1 root root 776 Jun 20 17:01 filter.o
  # readelf -SW filter.o
  There are 7 section headers, starting at offset 0x148:

  Section Headers:
   [Nr] NameType   Address  OffSize   ES Flg Lk Inf Al
   [ 0] NULL    00 00 00  0   0  0
   [ 1] .strtab STRTAB  e8 5a 00  0   0  1
   [ 2] .text   PROGBITS    40 00 00  AX  0   0  4
   [ 3] func=hrtimer_nanosleep rqtp->tv_nsec PROGBITS  40 
28 00  AX  0   0  8
   [ 4] license PROGBITS    68 04 00  WA  0   0  1
   [ 5] version PROGBITS    6c 04 00  WA  0   0  4
   [ 6] .symtab SYMTAB  70 78 18  1   2  8
  Key to Flags:
   W (write), A (alloc), X (execute), M (merge), S (strings)
   I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
   O (extra OS processing required) o (OS specific), p (processor specific)
   #

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: Jiri Olsa 
Cc: pi3or...@163.com
Link: 
http://lkml.kernel.org/r/1466064161-48553-2-git-send-email-wangn...@huawei.com
[ s/dumpping/dumping/g ]
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/util/llvm-utils.c | 42 ++
 tools/perf/util/llvm-utils.h |  5 +
 2 files changed, 47 insertions(+)

diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 33071d6..878a566 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -42,6 +42,8 @@ int perf_llvm_config(const char *var, const char *value)
llvm_param.kbuild_dir = strdup(value);
else if (!strcmp(var, "kbuild-opts"))
llvm_param.kbuild_opts = strdup(value);
+   else if (!strcmp(var, "dump-obj"))
+   llvm_param.dump_obj = !!perf_config_bool(var, value);
else
return -1;
llvm_param.user_set_param = true;
@@ -326,6 +328,42 @@ get_kbuild_opts(char **kbuild_dir, char 
**kbuild_include_opts)
pr_debug("include option is set to %s\n", *kbuild_include_opts);
 }
 
+static void
+dump_obj(const char *path, void *obj_buf, size_t size)
+{
+   char *obj_path = strdup(path);
+   FILE *fp;
+   char *p;
+
+   if (!obj_path) {
+   pr_warning("WARNING: No enough memory, skip object dumping\n");
+   return;
+   }
+
+   p = strrchr(obj_path, '.');
+   if (!p || (strcmp(p, ".c") != 0)) {
+   pr_warning("WARNING: invalid llvm source path: '%s', skip 
object dumping\n",
+  obj_path);
+   goto out;
+   }
+
+   p[1] = 'o';
+   fp = fopen(obj_path, "wb");
+   if (!fp) {
+   pr_warning("WARNING: failed to open '%s': %s, skip object 
dumping\n",
+  obj_path, strerror(errno));
+   goto out;
+   }
+
+   pr_info("LLVM: dumping %s\n", obj_path);
+   if (fwrite(obj_buf, size, 1, fp) != 1)
+   pr_warning("WARNING: failed to write to 

[tip:perf/core] perf llvm: Allow dump llvm output object file using llvm.dump-obj

2016-06-22 Thread tip-bot for Wang Nan
Commit-ID:  f078464925f5b5c977c1196c67cae49cd82f40ff
Gitweb: http://git.kernel.org/tip/f078464925f5b5c977c1196c67cae49cd82f40ff
Author: Wang Nan 
AuthorDate: Thu, 16 Jun 2016 08:02:40 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 21 Jun 2016 13:18:34 -0300

perf llvm: Allow dump llvm output object file using llvm.dump-obj

Add a 'llvm.dump-obj' config option to enable perf dump BPF object files
compiled by LLVM.

This option is useful when using BPF objects in embedded platforms.
LLVM compiler won't be deployed in these platforms, and currently we
don't support dynamic compiling library.

Before this patch users have to explicitly issue llvm commands to
compile BPF scripts, and can't use helpers (like include path detection
and default macros) in perf. With this option, user is allowed to use
perf to compile their BPF objects then copy them into their embedded
platforms.

Committer notice:

Testing it:

  # cat ~/.perfconfig
  [llvm]
dump-obj = true
  #
  # ls -la filter.o
  ls: cannot access filter.o: No such file or directory
  # cat filter.c
  #include 
  #define SEC(NAME) __attribute__((section(NAME), used))

  SEC("func=hrtimer_nanosleep rqtp->tv_nsec")
  int func(void *ctx, int err, long nsec)
  {
return nsec > 1000;
  }
  char _license[] SEC("license") = "GPL";
  int _version SEC("version") = LINUX_VERSION_CODE;
  # trace -e nanosleep --event filter.c usleep 6
  LLVM: dumping filter.o
 0.007 ( 0.007 ms): usleep/13976 nanosleep(rqtp: 0x7ffc5847f640 
   ) ...
 0.007 ( ): perf_bpf_probe:func:(811137d0) tv_nsec=6000)
 0.070 ( 0.070 ms): usleep/13976  ... [continued]: nanosleep()) = 0
  # ls -la filter.o
  -rw-r--r--. 1 root root 776 Jun 20 17:01 filter.o
  # readelf -SW filter.o
  There are 7 section headers, starting at offset 0x148:

  Section Headers:
   [Nr] NameType   Address  OffSize   ES Flg Lk Inf Al
   [ 0] NULL    00 00 00  0   0  0
   [ 1] .strtab STRTAB  e8 5a 00  0   0  1
   [ 2] .text   PROGBITS    40 00 00  AX  0   0  4
   [ 3] func=hrtimer_nanosleep rqtp->tv_nsec PROGBITS  40 
28 00  AX  0   0  8
   [ 4] license PROGBITS    68 04 00  WA  0   0  1
   [ 5] version PROGBITS    6c 04 00  WA  0   0  4
   [ 6] .symtab SYMTAB  70 78 18  1   2  8
  Key to Flags:
   W (write), A (alloc), X (execute), M (merge), S (strings)
   I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
   O (extra OS processing required) o (OS specific), p (processor specific)
   #

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: Jiri Olsa 
Cc: pi3or...@163.com
Link: 
http://lkml.kernel.org/r/1466064161-48553-2-git-send-email-wangn...@huawei.com
[ s/dumpping/dumping/g ]
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/util/llvm-utils.c | 42 ++
 tools/perf/util/llvm-utils.h |  5 +
 2 files changed, 47 insertions(+)

diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 33071d6..878a566 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -42,6 +42,8 @@ int perf_llvm_config(const char *var, const char *value)
llvm_param.kbuild_dir = strdup(value);
else if (!strcmp(var, "kbuild-opts"))
llvm_param.kbuild_opts = strdup(value);
+   else if (!strcmp(var, "dump-obj"))
+   llvm_param.dump_obj = !!perf_config_bool(var, value);
else
return -1;
llvm_param.user_set_param = true;
@@ -326,6 +328,42 @@ get_kbuild_opts(char **kbuild_dir, char 
**kbuild_include_opts)
pr_debug("include option is set to %s\n", *kbuild_include_opts);
 }
 
+static void
+dump_obj(const char *path, void *obj_buf, size_t size)
+{
+   char *obj_path = strdup(path);
+   FILE *fp;
+   char *p;
+
+   if (!obj_path) {
+   pr_warning("WARNING: No enough memory, skip object dumping\n");
+   return;
+   }
+
+   p = strrchr(obj_path, '.');
+   if (!p || (strcmp(p, ".c") != 0)) {
+   pr_warning("WARNING: invalid llvm source path: '%s', skip 
object dumping\n",
+  obj_path);
+   goto out;
+   }
+
+   p[1] = 'o';
+   fp = fopen(obj_path, "wb");
+   if (!fp) {
+   pr_warning("WARNING: failed to open '%s': %s, skip object 
dumping\n",
+  obj_path, strerror(errno));
+   goto out;
+   }
+
+   pr_info("LLVM: dumping %s\n", obj_path);
+   if (fwrite(obj_buf, size, 1, fp) != 1)
+   pr_warning("WARNING: failed to write to file '%s': %s, skip 
object dumping\n",
+  obj_path, strerror(errno));
+