linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/30] perf clang: Builtin clang and perfhook support
@ 2016-11-26  7:03 Wang Nan
  2016-11-26  7:03 ` [PATCH v3 01/30] tools lib bpf: Add missing BPF functions Wang Nan
                   ` (29 more replies)
  0 siblings, 30 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

This is version 3 of perf builtin clang and perfhook patch series.
Compare to v2 there is only minor changes:
 1. BPF map helpers in perf hooks now called 'perf_map_...',
    instead of 'jit_helper_map_...'.
    (Alexei Starovoitov)
 2. Rename bpf_map_{pin,get} to bpf_obj_{pin,get}, make them consist
    with kernel.
    (Joe Stringer).

Example in v2 should be changed accordingly:

  $ cat ./count_syscalls.c
  typedef unsigned long u64;
  
  #define BPF_MAP_TYPE_HASH 1
  #define BPF_MAP_TYPE_ARRAY 2
  
  enum GVAL {
      G_perf_pid,
      NR_GVALS
  };
  
  struct bpf_map_def SEC("maps") GVALS = {
      .type = BPF_MAP_TYPE_ARRAY,
      .key_size = sizeof(int),
      .value_size = sizeof(u64),
      .max_entries = NR_GVALS,
  };
  
  struct bpf_map_def SEC("maps") syscall_counter = {
      .type = BPF_MAP_TYPE_HASH,
      .key_size = sizeof(u64),
      .value_size = sizeof(u64),
      .max_entries = 512,
  };
  
  SEC("raw_syscalls:sys_enter")
  int func(void *ctx)
  {
      int key = G_perf_pid;
      u64 id = *((u64 *)(ctx + 8));
      int self_pid = bpf_get_current_pid_tgid() & 0xffffffff;
      int *perf_pid = bpf_map_lookup_elem(&GVALS, &key);
      u64 *counter;
  
      if (!perf_pid)
          return 0;
      if (*perf_pid == self_pid)
          return 0;
      counter = bpf_map_lookup_elem(&syscall_counter, &id);
      if (!counter) {
          u64 value = 1;
          bpf_map_update_elem(&syscall_counter, &id, &value, 0);
          return 0;
      }
      __sync_fetch_and_add(counter, 1);
      return 0;
  }
  
  SEC("perfhook:record_start")
  void record_start(void *ctx)
  {
      int perf_pid = getpid(), key = G_perf_pid;
      printf("Start count, perfpid=%d\n", perf_pid);
      perf_map_update_elem(ctx, &GVALS, &key, &perf_pid, 0);
  }
  
  SEC("perfhook:record_end")
  void record_end(void *ctx)
  {
      u64 key = -1, value;
      while (!perf_map_get_next_key(ctx, &syscall_counter, &key, &key)) {
          perf_map_lookup_elem(ctx, &syscall_counter, &key, &value);
          printf("syscall %ld\tcount: %ld\n", (long)key, (long)value);
      }
  }
  char _license[] SEC("license") = "GPL";
  int _version SEC("version") = LINUX_VERSION_CODE;
  $ sudo -s
  # ulimit -l unlimited
  # perf record -e ./count_syscalls.c echo "Haha"
  Start count, perfpid=25209
  Haha
  [ perf record: Woken up 1 times to write data ]
  syscall 293	count: 2
  syscall 8	count: 7
  syscall 11	count: 763
  syscall 4	count: 43
  syscall 21	count: 48
  syscall 86	count: 1
  syscall 5	count: 791
  ...

Wang Nan (30):
  tools lib bpf: Add missing BPF functions
  tools lib bpf: Add private field for bpf_object
  tools lib bpf: Retrive bpf_map through offset of bpf_map_def
  perf tools: Introduce perf hooks
  perf tools: Pass context to perf hook functions
  perf llvm: Extract helpers in llvm-utils.c
  tools build: Add feature detection for LLVM
  tools build: Add feature detection for clang
  perf build: Add clang and llvm compile and linking support
  perf clang: Add builtin clang support ant test case
  perf clang: Use real file system for #include
  perf clang: Allow passing CFLAGS to builtin clang
  perf clang: Update test case to use real BPF script
  perf clang: Support compile IR to BPF object and add testcase
  perf clang: Compile BPF script use builtin clang support
  perf clang: Pass full path to builtin clang
  perf clang: Pass CFLAGS to builtin clang
  perf clang jit: Wrap llvm::Module using PerfModule
  perf clang jit: Insignt BPF and JIT functions in a Module
  perf clang jit: add PerfModule::doJIT to JIT perfhook functions
  perf clang jit: Export functions for jitted code
  perf clang jit: Actually JIT and hook in bpf loader
  perf clang jit: Collect the lowest address in maps section as map_base
  perf clang jit: Retrive fd of BPF map from its offset
  perf clang jit: Allow jitted perf hook access BPF maps
  perf clang: Link BPF functions declaration into perf
  perf clang: Declare BPF functions for BPF scripts automatically
  perf clang: Include helpers to BPF scripts
  perf clang builtin: Define hook helpers by default
  perf clang jit: Export getpid() to perf hook

 tools/build/feature/Makefile                  |  18 +
 tools/build/feature/test-clang.cpp            |  21 ++
 tools/build/feature/test-llvm.cpp             |   8 +
 tools/lib/bpf/bpf.c                           |  56 +++
 tools/lib/bpf/bpf.h                           |   7 +
 tools/lib/bpf/libbpf.c                        |  35 ++
 tools/lib/bpf/libbpf.h                        |  13 +
 tools/perf/Makefile.config                    |  62 +++-
 tools/perf/Makefile.perf                      |  23 +-
 tools/perf/builtin-record.c                   |  11 +
 tools/perf/tests/Build                        |   4 +-
 tools/perf/tests/bpf-script-example.c         |  30 +-
 tools/perf/tests/bpf-script-test-kbuild.c     |   2 +
 tools/perf/tests/bpf-script-test-prologue.c   |   6 +-
 tools/perf/tests/bpf-script-test-relocation.c |  17 +-
 tools/perf/tests/builtin-test.c               |  13 +
 tools/perf/tests/clang.c                      |  50 +++
 tools/perf/tests/llvm.h                       |   7 +
 tools/perf/tests/make                         |   2 +
 tools/perf/tests/perf-hooks.c                 |  48 +++
 tools/perf/tests/tests.h                      |   4 +
 tools/perf/util/Build                         |   5 +
 tools/perf/util/bpf-loader.c                  | 102 +++++-
 tools/perf/util/bpf-loader.h                  |  19 +
 tools/perf/util/c++/Build                     |   4 +
 tools/perf/util/c++/bpf-funcs-str.c           | 228 ++++++++++++
 tools/perf/util/c++/bpf-helper-str.c          |  23 ++
 tools/perf/util/c++/clang-bpf-includes.h      |  13 +
 tools/perf/util/c++/clang-c.h                 |  63 ++++
 tools/perf/util/c++/clang-test.cpp            |  99 +++++
 tools/perf/util/c++/clang.cpp                 | 497 ++++++++++++++++++++++++++
 tools/perf/util/c++/clang.h                   |  61 ++++
 tools/perf/util/jit-helpers.c                 |  57 +++
 tools/perf/util/jit-helpers.h                 |  28 ++
 tools/perf/util/llvm-utils.c                  |  76 +++-
 tools/perf/util/llvm-utils.h                  |  15 +-
 tools/perf/util/perf-hooks-list.h             |   3 +
 tools/perf/util/perf-hooks.c                  |  88 +++++
 tools/perf/util/perf-hooks.h                  |  39 ++
 tools/perf/util/util-cxx.h                    |  26 ++
 40 files changed, 1830 insertions(+), 53 deletions(-)
 create mode 100644 tools/build/feature/test-clang.cpp
 create mode 100644 tools/build/feature/test-llvm.cpp
 create mode 100644 tools/perf/tests/clang.c
 create mode 100644 tools/perf/tests/perf-hooks.c
 create mode 100644 tools/perf/util/c++/Build
 create mode 100644 tools/perf/util/c++/bpf-funcs-str.c
 create mode 100644 tools/perf/util/c++/bpf-helper-str.c
 create mode 100644 tools/perf/util/c++/clang-bpf-includes.h
 create mode 100644 tools/perf/util/c++/clang-c.h
 create mode 100644 tools/perf/util/c++/clang-test.cpp
 create mode 100644 tools/perf/util/c++/clang.cpp
 create mode 100644 tools/perf/util/c++/clang.h
 create mode 100644 tools/perf/util/jit-helpers.c
 create mode 100644 tools/perf/util/jit-helpers.h
 create mode 100644 tools/perf/util/perf-hooks-list.h
 create mode 100644 tools/perf/util/perf-hooks.c
 create mode 100644 tools/perf/util/perf-hooks.h
 create mode 100644 tools/perf/util/util-cxx.h

Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com

-- 
2.10.1

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [PATCH v3 01/30] tools lib bpf: Add missing BPF functions
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26 17:10   ` Alexei Starovoitov
  2016-12-02 10:37   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 02/30] tools lib bpf: Add private field for bpf_object Wang Nan
                   ` (28 subsequent siblings)
  29 siblings, 2 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast; +Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan

Add more BPF map operations to libbpf. Also add bpf_obj_{pin,get}(). They
can be used on not only BPF maps but also BPF programs.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Joe Stringer <joe@ovn.org>
Cc: Li Zefan <lizefan@huawei.com>
---
 tools/lib/bpf/bpf.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/bpf.h |  7 +++++++
 2 files changed, 63 insertions(+)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 4212ed6..8143536 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -110,3 +110,59 @@ int bpf_map_update_elem(int fd, void *key, void *value,
 
 	return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
 }
+
+int bpf_map_lookup_elem(int fd, void *key, void *value)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.map_fd = fd;
+	attr.key = ptr_to_u64(key);
+	attr.value = ptr_to_u64(value);
+
+	return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
+}
+
+int bpf_map_delete_elem(int fd, void *key)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.map_fd = fd;
+	attr.key = ptr_to_u64(key);
+
+	return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
+}
+
+int bpf_map_get_next_key(int fd, void *key, void *next_key)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.map_fd = fd;
+	attr.key = ptr_to_u64(key);
+	attr.next_key = ptr_to_u64(next_key);
+
+	return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
+}
+
+int bpf_obj_pin(int fd, const char *pathname)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.pathname = ptr_to_u64((void *)pathname);
+	attr.bpf_fd = fd;
+
+	return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
+}
+
+int bpf_obj_get(const char *pathname)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.pathname = ptr_to_u64((void *)pathname);
+
+	return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
+}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index e8ba540..253c3db 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -35,4 +35,11 @@ int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
 
 int bpf_map_update_elem(int fd, void *key, void *value,
 			u64 flags);
+
+int bpf_map_lookup_elem(int fd, void *key, void *value);
+int bpf_map_delete_elem(int fd, void *key);
+int bpf_map_get_next_key(int fd, void *key, void *next_key);
+int bpf_obj_pin(int fd, const char *pathname);
+int bpf_obj_get(const char *pathname);
+
 #endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 02/30] tools lib bpf: Add private field for bpf_object
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
  2016-11-26  7:03 ` [PATCH v3 01/30] tools lib bpf: Add missing BPF functions Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26 17:11   ` Alexei Starovoitov
  2016-12-02 10:37   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 03/30] tools lib bpf: Retrive bpf_map through offset of bpf_map_def Wang Nan
                   ` (27 subsequent siblings)
  29 siblings, 2 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast; +Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan

Similar to other classes defined in libbpf.h (map and program), allow
'object' class has its own private data.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Li Zefan <lizefan@huawei.com>
---
 tools/lib/bpf/libbpf.c | 23 +++++++++++++++++++++++
 tools/lib/bpf/libbpf.h |  5 +++++
 2 files changed, 28 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 96a2b2f..866d5cd 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -229,6 +229,10 @@ struct bpf_object {
 	 * all objects.
 	 */
 	struct list_head list;
+
+	void *priv;
+	bpf_object_clear_priv_t clear_priv;
+
 	char path[];
 };
 #define obj_elf_valid(o)	((o)->efile.elf)
@@ -1229,6 +1233,9 @@ void bpf_object__close(struct bpf_object *obj)
 	if (!obj)
 		return;
 
+	if (obj->clear_priv)
+		obj->clear_priv(obj, obj->priv);
+
 	bpf_object__elf_finish(obj);
 	bpf_object__unload(obj);
 
@@ -1282,6 +1289,22 @@ unsigned int bpf_object__kversion(struct bpf_object *obj)
 	return obj ? obj->kern_version : 0;
 }
 
+int bpf_object__set_priv(struct bpf_object *obj, void *priv,
+			 bpf_object_clear_priv_t clear_priv)
+{
+	if (obj->priv && obj->clear_priv)
+		obj->clear_priv(obj, obj->priv);
+
+	obj->priv = priv;
+	obj->clear_priv = clear_priv;
+	return 0;
+}
+
+void *bpf_object__priv(struct bpf_object *obj)
+{
+	return obj ? obj->priv : ERR_PTR(-EINVAL);
+}
+
 struct bpf_program *
 bpf_program__next(struct bpf_program *prev, struct bpf_object *obj)
 {
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index dd7a513..0c0b012 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -79,6 +79,11 @@ struct bpf_object *bpf_object__next(struct bpf_object *prev);
 	     (pos) != NULL;				\
 	     (pos) = (tmp), (tmp) = bpf_object__next(tmp))
 
+typedef void (*bpf_object_clear_priv_t)(struct bpf_object *, void *);
+int bpf_object__set_priv(struct bpf_object *obj, void *priv,
+			 bpf_object_clear_priv_t clear_priv);
+void *bpf_object__priv(struct bpf_object *prog);
+
 /* Accessors of bpf_program. */
 struct bpf_program;
 struct bpf_program *bpf_program__next(struct bpf_program *prog,
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 03/30] tools lib bpf: Retrive bpf_map through offset of bpf_map_def
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
  2016-11-26  7:03 ` [PATCH v3 01/30] tools lib bpf: Add missing BPF functions Wang Nan
  2016-11-26  7:03 ` [PATCH v3 02/30] tools lib bpf: Add private field for bpf_object Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26 17:12   ` Alexei Starovoitov
  2016-12-02 10:38   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 04/30] perf tools: Introduce perf hooks Wang Nan
                   ` (26 subsequent siblings)
  29 siblings, 2 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan,
	Alexei Starovoitov, Jiri Olsa

Add a new API to libbpf, caller is able to get bpf_map through the
offset of bpf_map_def to 'maps' section.

The API will be used to help jitted perf hook code find fd of a map.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/lib/bpf/libbpf.c | 12 ++++++++++++
 tools/lib/bpf/libbpf.h |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 866d5cd..2e97459 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1524,3 +1524,15 @@ bpf_object__find_map_by_name(struct bpf_object *obj, const char *name)
 	}
 	return NULL;
 }
+
+struct bpf_map *
+bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset)
+{
+	int i;
+
+	for (i = 0; i < obj->nr_maps; i++) {
+		if (obj->maps[i].offset == offset)
+			return &obj->maps[i];
+	}
+	return ERR_PTR(-ENOENT);
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 0c0b012..a5a8b86 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -24,6 +24,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <linux/err.h>
+#include <sys/types.h>  // for size_t
 
 enum libbpf_errno {
 	__LIBBPF_ERRNO__START = 4000,
@@ -200,6 +201,13 @@ struct bpf_map;
 struct bpf_map *
 bpf_object__find_map_by_name(struct bpf_object *obj, const char *name);
 
+/*
+ * Get bpf_map through the offset of corresponding struct bpf_map_def
+ * in the bpf object file.
+ */
+struct bpf_map *
+bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset);
+
 struct bpf_map *
 bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
 #define bpf_map__for_each(pos, obj)		\
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 04/30] perf tools: Introduce perf hooks
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (2 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 03/30] tools lib bpf: Retrive bpf_map through offset of bpf_map_def Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-12-02 10:38   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 05/30] perf tools: Pass context to perf hook functions Wang Nan
                   ` (25 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Perf hooks allow hooking user code at perf events. They can be used for
manipulation of BPF maps, taking snapshot and reporting results. In this
patch two perf hook points are introduced: record_start and record_end.

To avoid buggy user actions, a SIGSEGV signal handler is introduced into
'perf record'. It turns off perf hook if it causes a segfault and report
an error to help debugging.

A test case for perf hook is introduced.

Test result:
  $ ./buildperf/perf test -v hook
  50: Test perf hooks                                          :
  --- start ---
  test child forked, pid 10311
  SIGSEGV is observed as expected, try to recover.
  Fatal error (SEGFAULT) in perf hook 'test'
  test child finished with 0
  ---- end ----
  Test perf hooks: Ok

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-record.c       | 11 +++++
 tools/perf/tests/Build            |  1 +
 tools/perf/tests/builtin-test.c   |  4 ++
 tools/perf/tests/perf-hooks.c     | 44 ++++++++++++++++++++
 tools/perf/tests/tests.h          |  1 +
 tools/perf/util/Build             |  2 +
 tools/perf/util/perf-hooks-list.h |  3 ++
 tools/perf/util/perf-hooks.c      | 84 +++++++++++++++++++++++++++++++++++++++
 tools/perf/util/perf-hooks.h      | 37 +++++++++++++++++
 9 files changed, 187 insertions(+)
 create mode 100644 tools/perf/tests/perf-hooks.c
 create mode 100644 tools/perf/util/perf-hooks-list.h
 create mode 100644 tools/perf/util/perf-hooks.c
 create mode 100644 tools/perf/util/perf-hooks.h

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 67d2a90..fa26865 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -37,6 +37,7 @@
 #include "util/llvm-utils.h"
 #include "util/bpf-loader.h"
 #include "util/trigger.h"
+#include "util/perf-hooks.h"
 #include "asm/bug.h"
 
 #include <unistd.h>
@@ -206,6 +207,12 @@ static void sig_handler(int sig)
 	done = 1;
 }
 
+static void sigsegv_handler(int sig)
+{
+	perf_hooks__recover();
+	sighandler_dump_stack(sig);
+}
+
 static void record__sig_exit(void)
 {
 	if (signr == -1)
@@ -833,6 +840,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 	signal(SIGCHLD, sig_handler);
 	signal(SIGINT, sig_handler);
 	signal(SIGTERM, sig_handler);
+	signal(SIGSEGV, sigsegv_handler);
 
 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
 		signal(SIGUSR2, snapshot_sig_handler);
@@ -970,6 +978,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 
 	trigger_ready(&auxtrace_snapshot_trigger);
 	trigger_ready(&switch_output_trigger);
+	perf_hooks__invoke_record_start();
 	for (;;) {
 		unsigned long long hits = rec->samples;
 
@@ -1114,6 +1123,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 		}
 	}
 
+	perf_hooks__invoke_record_end();
+
 	if (!err && !quiet) {
 		char samples[128];
 		const char *postfix = rec->timestamp_filename ?
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 8a4ce49..af3ec94 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -42,6 +42,7 @@ perf-y += backward-ring-buffer.o
 perf-y += sdt.o
 perf-y += is_printable_array.o
 perf-y += bitmap.o
+perf-y += perf-hooks.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
 	$(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 778668a..dab83f7 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -230,6 +230,10 @@ static struct test generic_tests[] = {
 		.func = test__bitmap_print,
 	},
 	{
+		.desc = "Test perf hooks",
+		.func = test__perf_hooks,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/perf-hooks.c b/tools/perf/tests/perf-hooks.c
new file mode 100644
index 0000000..9338cb2
--- /dev/null
+++ b/tools/perf/tests/perf-hooks.c
@@ -0,0 +1,44 @@
+#include <signal.h>
+#include <stdlib.h>
+
+#include "tests.h"
+#include "debug.h"
+#include "util.h"
+#include "perf-hooks.h"
+
+static void sigsegv_handler(int sig __maybe_unused)
+{
+	pr_debug("SIGSEGV is observed as expected, try to recover.\n");
+	perf_hooks__recover();
+	signal(SIGSEGV, SIG_DFL);
+	raise(SIGSEGV);
+	exit(-1);
+}
+
+static int hook_flags;
+
+static void the_hook(void)
+{
+	int *p = NULL;
+
+	hook_flags = 1234;
+
+	/* Generate a segfault, test perf_hooks__recover */
+	*p = 0;
+}
+
+int test__perf_hooks(int subtest __maybe_unused)
+{
+	signal(SIGSEGV, sigsegv_handler);
+	perf_hooks__set_hook("test", the_hook);
+	perf_hooks__invoke_test();
+
+	/* hook is triggered? */
+	if (hook_flags != 1234)
+		return TEST_FAIL;
+
+	/* the buggy hook is removed? */
+	if (perf_hooks__get_hook("test"))
+		return TEST_FAIL;
+	return TEST_OK;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 7c196c5..3a1f98f 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -91,6 +91,7 @@ int test__cpu_map_print(int subtest);
 int test__sdt_event(int subtest);
 int test__is_printable_array(int subtest);
 int test__bitmap_print(int subtest);
+int test__perf_hooks(int subtest);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 1dc67ef..b2a47aa 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -123,6 +123,8 @@ libperf-$(CONFIG_LIBELF) += genelf.o
 libperf-$(CONFIG_DWARF) += genelf_debug.o
 endif
 
+libperf-y += perf-hooks.o
+
 CFLAGS_config.o   += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
 # avoid compiler warnings in 32-bit mode
 CFLAGS_genelf_debug.o  += -Wno-packed
diff --git a/tools/perf/util/perf-hooks-list.h b/tools/perf/util/perf-hooks-list.h
new file mode 100644
index 0000000..2867c07
--- /dev/null
+++ b/tools/perf/util/perf-hooks-list.h
@@ -0,0 +1,3 @@
+PERF_HOOK(record_start)
+PERF_HOOK(record_end)
+PERF_HOOK(test)
diff --git a/tools/perf/util/perf-hooks.c b/tools/perf/util/perf-hooks.c
new file mode 100644
index 0000000..4ce88e3
--- /dev/null
+++ b/tools/perf/util/perf-hooks.c
@@ -0,0 +1,84 @@
+/*
+ * perf_hooks.c
+ *
+ * Copyright (C) 2016 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2016 Huawei Inc.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <linux/err.h>
+#include "util/util.h"
+#include "util/debug.h"
+#include "util/perf-hooks.h"
+
+static sigjmp_buf jmpbuf;
+static const struct perf_hook_desc *current_perf_hook;
+
+void perf_hooks__invoke(const struct perf_hook_desc *desc)
+{
+	if (!(desc && desc->p_hook_func && *desc->p_hook_func))
+		return;
+
+	if (sigsetjmp(jmpbuf, 1)) {
+		pr_warning("Fatal error (SEGFAULT) in perf hook '%s'\n",
+			   desc->hook_name);
+		*(current_perf_hook->p_hook_func) = NULL;
+	} else {
+		current_perf_hook = desc;
+		(**desc->p_hook_func)();
+	}
+	current_perf_hook = NULL;
+}
+
+void perf_hooks__recover(void)
+{
+	if (current_perf_hook)
+		siglongjmp(jmpbuf, 1);
+}
+
+#define PERF_HOOK(name)					\
+perf_hook_func_t __perf_hook_func_##name = NULL;	\
+struct perf_hook_desc __perf_hook_desc_##name =		\
+	{.hook_name = #name, .p_hook_func = &__perf_hook_func_##name};
+#include "perf-hooks-list.h"
+#undef PERF_HOOK
+
+#define PERF_HOOK(name)		\
+	&__perf_hook_desc_##name,
+
+static struct perf_hook_desc *perf_hooks[] = {
+#include "perf-hooks-list.h"
+};
+#undef PERF_HOOK
+
+int perf_hooks__set_hook(const char *hook_name,
+			 perf_hook_func_t hook_func)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(perf_hooks); i++) {
+		if (strcmp(hook_name, perf_hooks[i]->hook_name) != 0)
+			continue;
+
+		if (*(perf_hooks[i]->p_hook_func))
+			pr_warning("Overwrite existing hook: %s\n", hook_name);
+		*(perf_hooks[i]->p_hook_func) = hook_func;
+		return 0;
+	}
+	return -ENOENT;
+}
+
+perf_hook_func_t perf_hooks__get_hook(const char *hook_name)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(perf_hooks); i++) {
+		if (strcmp(hook_name, perf_hooks[i]->hook_name) != 0)
+			continue;
+
+		return *(perf_hooks[i]->p_hook_func);
+	}
+	return ERR_PTR(-ENOENT);
+}
diff --git a/tools/perf/util/perf-hooks.h b/tools/perf/util/perf-hooks.h
new file mode 100644
index 0000000..1d482b2
--- /dev/null
+++ b/tools/perf/util/perf-hooks.h
@@ -0,0 +1,37 @@
+#ifndef PERF_UTIL_PERF_HOOKS_H
+#define PERF_UTIL_PERF_HOOKS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*perf_hook_func_t)(void);
+struct perf_hook_desc {
+	const char * const hook_name;
+	perf_hook_func_t * const p_hook_func;
+};
+
+extern void perf_hooks__invoke(const struct perf_hook_desc *);
+extern void perf_hooks__recover(void);
+
+#define PERF_HOOK(name)					\
+extern struct perf_hook_desc __perf_hook_desc_##name;	\
+static inline void perf_hooks__invoke_##name(void)	\
+{ 							\
+	perf_hooks__invoke(&__perf_hook_desc_##name);	\
+}
+
+#include "perf-hooks-list.h"
+#undef PERF_HOOK
+
+extern int
+perf_hooks__set_hook(const char *hook_name,
+		     perf_hook_func_t hook_func);
+
+extern perf_hook_func_t
+perf_hooks__get_hook(const char *hook_name);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 05/30] perf tools: Pass context to perf hook functions
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (3 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 04/30] perf tools: Introduce perf hooks Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-12-06  8:21   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 06/30] perf llvm: Extract helpers in llvm-utils.c Wang Nan
                   ` (24 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Pass a pointer to perf hook functions so they receive context
information created durnig setup.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/tests/perf-hooks.c | 14 +++++++++-----
 tools/perf/util/perf-hooks.c  | 10 +++++++---
 tools/perf/util/perf-hooks.h  |  6 ++++--
 3 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/tools/perf/tests/perf-hooks.c b/tools/perf/tests/perf-hooks.c
index 9338cb2..665ecc1 100644
--- a/tools/perf/tests/perf-hooks.c
+++ b/tools/perf/tests/perf-hooks.c
@@ -15,13 +15,13 @@ static void sigsegv_handler(int sig __maybe_unused)
 	exit(-1);
 }
 
-static int hook_flags;
 
-static void the_hook(void)
+static void the_hook(void *_hook_flags)
 {
+	int *hook_flags = _hook_flags;
 	int *p = NULL;
 
-	hook_flags = 1234;
+	*hook_flags = 1234;
 
 	/* Generate a segfault, test perf_hooks__recover */
 	*p = 0;
@@ -29,13 +29,17 @@ static void the_hook(void)
 
 int test__perf_hooks(int subtest __maybe_unused)
 {
+	int hook_flags = 0;
+
 	signal(SIGSEGV, sigsegv_handler);
-	perf_hooks__set_hook("test", the_hook);
+	perf_hooks__set_hook("test", the_hook, &hook_flags);
 	perf_hooks__invoke_test();
 
 	/* hook is triggered? */
-	if (hook_flags != 1234)
+	if (hook_flags != 1234) {
+		pr_debug("Setting failed: %d (%p)\n", hook_flags, &hook_flags);
 		return TEST_FAIL;
+	}
 
 	/* the buggy hook is removed? */
 	if (perf_hooks__get_hook("test"))
diff --git a/tools/perf/util/perf-hooks.c b/tools/perf/util/perf-hooks.c
index 4ce88e3..cb36830 100644
--- a/tools/perf/util/perf-hooks.c
+++ b/tools/perf/util/perf-hooks.c
@@ -27,7 +27,7 @@ void perf_hooks__invoke(const struct perf_hook_desc *desc)
 		*(current_perf_hook->p_hook_func) = NULL;
 	} else {
 		current_perf_hook = desc;
-		(**desc->p_hook_func)();
+		(**desc->p_hook_func)(desc->hook_ctx);
 	}
 	current_perf_hook = NULL;
 }
@@ -41,7 +41,9 @@ void perf_hooks__recover(void)
 #define PERF_HOOK(name)					\
 perf_hook_func_t __perf_hook_func_##name = NULL;	\
 struct perf_hook_desc __perf_hook_desc_##name =		\
-	{.hook_name = #name, .p_hook_func = &__perf_hook_func_##name};
+	{.hook_name = #name,				\
+	 .p_hook_func = &__perf_hook_func_##name,	\
+	 .hook_ctx = NULL};
 #include "perf-hooks-list.h"
 #undef PERF_HOOK
 
@@ -54,7 +56,8 @@ static struct perf_hook_desc *perf_hooks[] = {
 #undef PERF_HOOK
 
 int perf_hooks__set_hook(const char *hook_name,
-			 perf_hook_func_t hook_func)
+			 perf_hook_func_t hook_func,
+			 void *hook_ctx)
 {
 	unsigned int i;
 
@@ -65,6 +68,7 @@ int perf_hooks__set_hook(const char *hook_name,
 		if (*(perf_hooks[i]->p_hook_func))
 			pr_warning("Overwrite existing hook: %s\n", hook_name);
 		*(perf_hooks[i]->p_hook_func) = hook_func;
+		perf_hooks[i]->hook_ctx = hook_ctx;
 		return 0;
 	}
 	return -ENOENT;
diff --git a/tools/perf/util/perf-hooks.h b/tools/perf/util/perf-hooks.h
index 1d482b2..838d579 100644
--- a/tools/perf/util/perf-hooks.h
+++ b/tools/perf/util/perf-hooks.h
@@ -5,10 +5,11 @@
 extern "C" {
 #endif
 
-typedef void (*perf_hook_func_t)(void);
+typedef void (*perf_hook_func_t)(void *ctx);
 struct perf_hook_desc {
 	const char * const hook_name;
 	perf_hook_func_t * const p_hook_func;
+	void *hook_ctx;
 };
 
 extern void perf_hooks__invoke(const struct perf_hook_desc *);
@@ -26,7 +27,8 @@ static inline void perf_hooks__invoke_##name(void)	\
 
 extern int
 perf_hooks__set_hook(const char *hook_name,
-		     perf_hook_func_t hook_func);
+		     perf_hook_func_t hook_func,
+		     void *hook_ctx);
 
 extern perf_hook_func_t
 perf_hooks__get_hook(const char *hook_name);
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 06/30] perf llvm: Extract helpers in llvm-utils.c
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (4 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 05/30] perf tools: Pass context to perf hook functions Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-12-06  8:21   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 07/30] tools build: Add feature detection for LLVM Wang Nan
                   ` (23 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Following commits will use builtin clang to compile BPF script.
llvm__get_kbuild_opts() and llvm__get_nr_cpus() are extracted to help
building '-DKERNEL_VERSION_CODE' and '-D__NR_CPUS__' macros.

Doing object dumping in bpf loader, so futher builtin clang compiling
needn't consider it.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/bpf-loader.c |  4 +++
 tools/perf/util/llvm-utils.c | 76 +++++++++++++++++++++++++++++++++-----------
 tools/perf/util/llvm-utils.h |  6 ++++
 3 files changed, 68 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index a5fd275..cf16b941 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -90,6 +90,10 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 		if (err)
 			return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
 		obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
+
+		if (!IS_ERR(obj) && llvm_param.dump_obj)
+			llvm__dump_obj(filename, obj_buf, obj_buf_sz);
+
 		free(obj_buf);
 	} else
 		obj = bpf_object__open(filename);
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 27b6f303..b23ff44 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -7,6 +7,7 @@
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <linux/err.h>
 #include "debug.h"
 #include "llvm-utils.h"
 #include "config.h"
@@ -282,9 +283,10 @@ static const char *kinc_fetch_script =
 "rm -rf $TMPDIR\n"
 "exit $RET\n";
 
-static inline void
-get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
+void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 {
+	static char *saved_kbuild_dir;
+	static char *saved_kbuild_include_opts;
 	int err;
 
 	if (!kbuild_dir || !kbuild_include_opts)
@@ -293,10 +295,28 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 	*kbuild_dir = NULL;
 	*kbuild_include_opts = NULL;
 
+	if (saved_kbuild_dir && saved_kbuild_include_opts &&
+	    !IS_ERR(saved_kbuild_dir) && !IS_ERR(saved_kbuild_include_opts)) {
+		*kbuild_dir = strdup(saved_kbuild_dir);
+		*kbuild_include_opts = strdup(saved_kbuild_include_opts);
+
+		if (*kbuild_dir && *kbuild_include_opts)
+			return;
+
+		zfree(kbuild_dir);
+		zfree(kbuild_include_opts);
+		/*
+		 * Don't fall through: it may breaks saved_kbuild_dir and
+		 * saved_kbuild_include_opts if detect them again when
+		 * memory is low.
+		 */
+		return;
+	}
+
 	if (llvm_param.kbuild_dir && !llvm_param.kbuild_dir[0]) {
 		pr_debug("[llvm.kbuild-dir] is set to \"\" deliberately.\n");
 		pr_debug("Skip kbuild options detection.\n");
-		return;
+		goto errout;
 	}
 
 	err = detect_kbuild_dir(kbuild_dir);
@@ -306,7 +326,7 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 "Hint:\tSet correct kbuild directory using 'kbuild-dir' option in [llvm]\n"
 "     \tsection of ~/.perfconfig or set it to \"\" to suppress kbuild\n"
 "     \tdetection.\n\n");
-		return;
+		goto errout;
 	}
 
 	pr_debug("Kernel build dir is set to %s\n", *kbuild_dir);
@@ -325,14 +345,43 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 
 		free(*kbuild_dir);
 		*kbuild_dir = NULL;
-		return;
+		goto errout;
 	}
 
 	pr_debug("include option is set to %s\n", *kbuild_include_opts);
+
+	saved_kbuild_dir = strdup(*kbuild_dir);
+	saved_kbuild_include_opts = strdup(*kbuild_include_opts);
+
+	if (!saved_kbuild_dir || !saved_kbuild_include_opts) {
+		zfree(&saved_kbuild_dir);
+		zfree(&saved_kbuild_include_opts);
+	}
+	return;
+errout:
+	saved_kbuild_dir = ERR_PTR(-EINVAL);
+	saved_kbuild_include_opts = ERR_PTR(-EINVAL);
 }
 
-static void
-dump_obj(const char *path, void *obj_buf, size_t size)
+int llvm__get_nr_cpus(void)
+{
+	static int nr_cpus_avail = 0;
+	char serr[STRERR_BUFSIZE];
+
+	if (nr_cpus_avail > 0)
+		return nr_cpus_avail;
+
+	nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
+	if (nr_cpus_avail <= 0) {
+		pr_err(
+"WARNING:\tunable to get available CPUs in this system: %s\n"
+"        \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
+		nr_cpus_avail = 128;
+	}
+	return nr_cpus_avail;
+}
+
+void llvm__dump_obj(const char *path, void *obj_buf, size_t size)
 {
 	char *obj_path = strdup(path);
 	FILE *fp;
@@ -406,15 +455,9 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
 	 * This is an optional work. Even it fail we can continue our
 	 * work. Needn't to check error return.
 	 */
-	get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
+	llvm__get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
 
-	nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
-	if (nr_cpus_avail <= 0) {
-		pr_err(
-"WARNING:\tunable to get available CPUs in this system: %s\n"
-"        \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
-		nr_cpus_avail = 128;
-	}
+	nr_cpus_avail = llvm__get_nr_cpus();
 	snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d",
 		 nr_cpus_avail);
 
@@ -453,9 +496,6 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
 	free(kbuild_dir);
 	free(kbuild_include_opts);
 
-	if (llvm_param.dump_obj)
-		dump_obj(path, obj_buf, obj_buf_sz);
-
 	if (!p_obj_buf)
 		free(obj_buf);
 	else
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h
index 9f501ce..c87a2a9 100644
--- a/tools/perf/util/llvm-utils.h
+++ b/tools/perf/util/llvm-utils.h
@@ -50,4 +50,10 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, size_t *p_obj_buf_sz);
 
 /* This function is for test__llvm() use only */
 int llvm__search_clang(void);
+
+/* Following functions are reused by builtin clang support */
+void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts);
+int llvm__get_nr_cpus(void);
+
+void llvm__dump_obj(const char *path, void *obj_buf, size_t size);
 #endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 07/30] tools build: Add feature detection for LLVM
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (5 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 06/30] perf llvm: Extract helpers in llvm-utils.c Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-12-06  8:22   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 08/30] tools build: Add feature detection for clang Wang Nan
                   ` (22 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Check if basic LLVM compiling environment is ready.

Use llvm-config to detect include and library directories. Avoid using
'llvm-config --cxxflags' because its result contain some unwanted flags
like --sysroot (if LLVM is built by yocto).

Use '?=' to set LLVM_CONFIG, so explicitly passing LLVM_CONFIG to make
would override it.

Use 'llvm-config --libs BPF' to check if BPF backend is compiled in.
Since now BPF bytecode is the only required backend, no need to waste
time linking llvm and clang if BPF backend is missing. This also
introduce an implicit requirement that LLVM should be new enough.  Old
LLVM doesn't support BPF backend.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1474874832-134786-4-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/build/feature/Makefile      | 8 ++++++++
 tools/build/feature/test-llvm.cpp | 8 ++++++++
 2 files changed, 16 insertions(+)
 create mode 100644 tools/build/feature/test-llvm.cpp

diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 8f668bc..c09de59 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -55,6 +55,7 @@ FILES := $(addprefix $(OUTPUT),$(FILES))
 CC := $(CROSS_COMPILE)gcc -MD
 CXX := $(CROSS_COMPILE)g++ -MD
 PKG_CONFIG := $(CROSS_COMPILE)pkg-config
+LLVM_CONFIG ?= llvm-config
 
 all: $(FILES)
 
@@ -229,6 +230,13 @@ $(OUTPUT)test-cxx.bin:
 $(OUTPUT)test-jvmti.bin:
 	$(BUILD)
 
+$(OUTPUT)test-llvm.bin:
+	$(BUILDXX) -std=gnu++11 					\
+		-I$(shell $(LLVM_CONFIG) --includedir) 		\
+		-L$(shell $(LLVM_CONFIG) --libdir)		\
+		$(shell $(LLVM_CONFIG) --libs Core BPF)		\
+		$(shell $(LLVM_CONFIG) --system-libs)
+
 -include $(OUTPUT)*.d
 
 ###############################
diff --git a/tools/build/feature/test-llvm.cpp b/tools/build/feature/test-llvm.cpp
new file mode 100644
index 0000000..d8d2cee
--- /dev/null
+++ b/tools/build/feature/test-llvm.cpp
@@ -0,0 +1,8 @@
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+int main()
+{
+	llvm::errs() << "Hello World!\n";
+	llvm::llvm_shutdown();
+	return 0;
+}
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 08/30] tools build: Add feature detection for clang
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (6 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 07/30] tools build: Add feature detection for LLVM Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-12-06  8:22   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 09/30] perf build: Add clang and llvm compile and linking support Wang Nan
                   ` (21 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Check if basic clang compiling environment is ready.

Doesn't like 'llvm-config --libs' which can returns llvm libraries in
right order and duplicates some libraries if necessary, there's no
correspondence for clang libraries (-lclangxxx). to avoid extra
complexity and to avoid new clang breaking libraries ordering, use
--start-group and --end-group.

In this test case, manually identify required clang libs and hope it to
be stable. Putting all clang libraries here is possible (use make's
wildcard), but then feature checking becomes very slow.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1474874832-134786-5-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/build/feature/Makefile       | 10 ++++++++++
 tools/build/feature/test-clang.cpp | 21 +++++++++++++++++++++
 2 files changed, 31 insertions(+)
 create mode 100644 tools/build/feature/test-clang.cpp

diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index c09de59..871d553 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -237,6 +237,16 @@ $(OUTPUT)test-llvm.bin:
 		$(shell $(LLVM_CONFIG) --libs Core BPF)		\
 		$(shell $(LLVM_CONFIG) --system-libs)
 
+$(OUTPUT)test-clang.bin:
+	$(BUILDXX) -std=gnu++11 					\
+		-I$(shell $(LLVM_CONFIG) --includedir) 		\
+		-L$(shell $(LLVM_CONFIG) --libdir)		\
+		-Wl,--start-group -lclangBasic -lclangDriver	\
+		  -lclangFrontend -lclangEdit -lclangLex	\
+		  -lclangAST -Wl,--end-group 			\
+		$(shell $(LLVM_CONFIG) --libs Core option)	\
+		$(shell $(LLVM_CONFIG) --system-libs)
+
 -include $(OUTPUT)*.d
 
 ###############################
diff --git a/tools/build/feature/test-clang.cpp b/tools/build/feature/test-clang.cpp
new file mode 100644
index 0000000..e23c1b1
--- /dev/null
+++ b/tools/build/feature/test-clang.cpp
@@ -0,0 +1,21 @@
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::driver;
+
+int main()
+{
+	IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+	IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+
+	DiagnosticsEngine Diags(DiagID, &*DiagOpts);
+	Driver TheDriver("test", "bpf-pc-linux", Diags);
+
+	llvm::llvm_shutdown();
+	return 0;
+}
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 09/30] perf build: Add clang and llvm compile and linking support
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (7 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 08/30] tools build: Add feature detection for clang Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-12-06  8:23   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 10/30] perf clang: Add builtin clang support ant test case Wang Nan
                   ` (20 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Add necessary c++ flags and link libraries to support builtin clang and
LLVM. Add all llvm and clang libraries, so don't need to worry about
clang changes its libraries setting. However, linking perf would take
much longer than usual.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1474874832-134786-6-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Makefile.config | 35 +++++++++++++++++++++++++++++++++++
 tools/perf/Makefile.perf   | 23 ++++++++++++++++++++++-
 tools/perf/tests/make      |  2 ++
 3 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 8a493d4..b7c9c80 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -136,6 +136,7 @@ endif
 # Treat warnings as errors unless directed not to
 ifneq ($(WERROR),0)
   CFLAGS += -Werror
+  CXXFLAGS += -Werror
 endif
 
 ifndef DEBUG
@@ -182,6 +183,13 @@ CFLAGS += -Wall
 CFLAGS += -Wextra
 CFLAGS += -std=gnu99
 
+CXXFLAGS += -std=gnu++11 -fno-exceptions -fno-rtti
+CXXFLAGS += -Wall
+CXXFLAGS += -fno-omit-frame-pointer
+CXXFLAGS += -ggdb3
+CXXFLAGS += -funwind-tables
+CXXFLAGS += -Wno-strict-aliasing
+
 # Enforce a non-executable stack, as we may regress (again) in the future by
 # adding assembler files missing the .GNU-stack linker note.
 LDFLAGS += -Wl,-z,noexecstack
@@ -783,6 +791,33 @@ ifndef NO_JVMTI
   endif
 endif
 
+USE_CXX = 0
+USE_CLANGLLVM = 0
+ifdef LIBCLANGLLVM
+  $(call feature_check,cxx)
+  ifneq ($(feature-cxx), 1)
+    msg := $(warning No g++ found, disable clang and llvm support. Please install g++)
+  else
+    $(call feature_check,llvm)
+    ifneq ($(feature-llvm), 1)
+      msg := $(warning No libLLVM found, disable clang and llvm support. Please install llvm-dev)
+    else
+      $(call feature_check,clang)
+      ifneq ($(feature-clang), 1)
+        msg := $(warning No libclang found, disable clang and llvm support. Please install libclang-dev)
+      else
+        CFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT
+        CXXFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT -I$(shell $(LLVM_CONFIG) --includedir)
+        $(call detected,CONFIG_CXX)
+        $(call detected,CONFIG_CLANGLLVM)
+	USE_CXX = 1
+	USE_LLVM = 1
+	USE_CLANG = 1
+      endif
+    endif
+  endif
+endif
+
 # Among the variables below, these:
 #   perfexecdir
 #   template_dir
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 3cb1df4..dfb20dd 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -88,6 +88,10 @@ include ../scripts/utilities.mak
 # and bypass the feature detection
 #
 # Define NO_JVMTI if you do not want jvmti agent built
+#
+# Define LIBCLANGLLVM if you DO want builtin clang and llvm support.
+# When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if
+# llvm-config is not in $PATH.
 
 # As per kernel Makefile, avoid funny character set dependencies
 unexport LC_ALL
@@ -143,6 +147,7 @@ endef
 $(call allow-override,CC,$(CROSS_COMPILE)gcc)
 $(call allow-override,AR,$(CROSS_COMPILE)ar)
 $(call allow-override,LD,$(CROSS_COMPILE)ld)
+$(call allow-override,CXX,$(CROSS_COMPILE)g++)
 
 LD += $(EXTRA_LDFLAGS)
 
@@ -151,6 +156,7 @@ HOSTLD  ?= ld
 HOSTAR  ?= ar
 
 PKG_CONFIG = $(CROSS_COMPILE)pkg-config
+LLVM_CONFIG ?= llvm-config
 
 RM      = rm -f
 LN      = ln -f
@@ -338,6 +344,21 @@ endif
 
 LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
 
+ifeq ($(USE_CLANG), 1)
+  CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization
+  LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) --libdir)/libclang$(l).a))
+  LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group
+endif
+
+ifeq ($(USE_LLVM), 1)
+  LIBLLVM = $(shell $(LLVM_CONFIG) --libs all) $(shell $(LLVM_CONFIG) --system-libs)
+  LIBS += -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM)
+endif
+
+ifeq ($(USE_CXX), 1)
+  LIBS += -lstdc++
+endif
+
 export INSTALL SHELL_PATH
 
 ### Build rules
@@ -356,7 +377,7 @@ strip: $(PROGRAMS) $(OUTPUT)perf
 
 PERF_IN := $(OUTPUT)perf-in.o
 
-export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
+export srctree OUTPUT RM CC CXX LD AR CFLAGS CXXFLAGS V BISON FLEX AWK
 export HOSTCC HOSTLD HOSTAR
 include $(srctree)/tools/build/Makefile.include
 
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 08ed7f1..aa49b66 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -83,6 +83,7 @@ make_no_libbpf	    := NO_LIBBPF=1
 make_no_libcrypto   := NO_LIBCRYPTO=1
 make_with_babeltrace:= LIBBABELTRACE=1
 make_no_sdt	    := NO_SDT=1
+make_with_clangllvm := LIBCLANGLLVM=1
 make_tags           := tags
 make_cscope         := cscope
 make_help           := help
@@ -139,6 +140,7 @@ run += make_no_libbionic
 run += make_no_auxtrace
 run += make_no_libbpf
 run += make_with_babeltrace
+run += make_with_clangllvm
 run += make_help
 run += make_doc
 run += make_perf_o
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (8 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 09/30] perf build: Add clang and llvm compile and linking support Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26 17:17   ` Alexei Starovoitov
                     ` (2 more replies)
  2016-11-26  7:03 ` [PATCH v3 11/30] perf clang: Use real file system for #include Wang Nan
                   ` (19 subsequent siblings)
  29 siblings, 3 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Add basic clang support in clang.cpp and test__clang() testcase. The
first testcase checks if builtin clang is able to generate LLVM IR.

tests/clang.c is a proxy. Real testcase resides in
utils/c++/clang-test.cpp in c++ and exports C interface to perf test
subsystem.

Test result:

   $ perf test -v clang
   51: Test builtin clang support                               :
   51.1: Test builtin clang compile C source to IR              :
   --- start ---
   test child forked, pid 13215
   test child finished with 0
   ---- end ----
   Test builtin clang support subtest 0: Ok

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/tests/Build             |  1 +
 tools/perf/tests/builtin-test.c    |  9 ++++
 tools/perf/tests/clang.c           | 42 +++++++++++++++++
 tools/perf/tests/tests.h           |  3 ++
 tools/perf/util/Build              |  2 +
 tools/perf/util/c++/Build          |  2 +
 tools/perf/util/c++/clang-c.h      | 16 +++++++
 tools/perf/util/c++/clang-test.cpp | 31 ++++++++++++
 tools/perf/util/c++/clang.cpp      | 96 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/c++/clang.h        | 16 +++++++
 10 files changed, 218 insertions(+)
 create mode 100644 tools/perf/tests/clang.c
 create mode 100644 tools/perf/util/c++/Build
 create mode 100644 tools/perf/util/c++/clang-c.h
 create mode 100644 tools/perf/util/c++/clang-test.cpp
 create mode 100644 tools/perf/util/c++/clang.cpp
 create mode 100644 tools/perf/util/c++/clang.h

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index af3ec94..6676c2d 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -43,6 +43,7 @@ perf-y += sdt.o
 perf-y += is_printable_array.o
 perf-y += bitmap.o
 perf-y += perf-hooks.o
+perf-y += clang.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
 	$(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index dab83f7..33aaa52 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -234,6 +234,15 @@ static struct test generic_tests[] = {
 		.func = test__perf_hooks,
 	},
 	{
+		.desc = "Test builtin clang support",
+		.func = test__clang,
+		.subtest = {
+			.skip_if_fail	= true,
+			.get_nr		= test__clang_subtest_get_nr,
+			.get_desc	= test__clang_subtest_get_desc,
+		}
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
new file mode 100644
index 0000000..57ee160
--- /dev/null
+++ b/tools/perf/tests/clang.c
@@ -0,0 +1,42 @@
+#include "tests.h"
+#include "debug.h"
+#include "util.h"
+#include "c++/clang-c.h"
+
+static struct {
+	int (*func)(void);
+	const char *desc;
+} clang_testcase_table[] = {
+#ifdef HAVE_LIBCLANGLLVM_SUPPORT
+	{
+		.func = test__clang_to_IR,
+		.desc = "Test builtin clang compile C source to IR",
+	},
+#endif
+};
+
+int test__clang_subtest_get_nr(void)
+{
+	return (int)ARRAY_SIZE(clang_testcase_table);
+}
+
+const char *test__clang_subtest_get_desc(int i)
+{
+	if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
+		return NULL;
+	return clang_testcase_table[i].desc;
+}
+
+#ifndef HAVE_LIBCLANGLLVM_SUPPORT
+int test__clang(int i __maybe_unused)
+{
+	return TEST_SKIP;
+}
+#else
+int test__clang(int i __maybe_unused)
+{
+	if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
+		return TEST_FAIL;
+	return clang_testcase_table[i].func();
+}
+#endif
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 3a1f98f..0d7b251 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -92,6 +92,9 @@ int test__sdt_event(int subtest);
 int test__is_printable_array(int subtest);
 int test__bitmap_print(int subtest);
 int test__perf_hooks(int subtest);
+int test__clang(int subtest);
+const char *test__clang_subtest_get_desc(int subtest);
+int test__clang_subtest_get_nr(void);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index b2a47aa..743a889 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -125,6 +125,8 @@ endif
 
 libperf-y += perf-hooks.o
 
+libperf-$(CONFIG_CXX) += c++/
+
 CFLAGS_config.o   += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
 # avoid compiler warnings in 32-bit mode
 CFLAGS_genelf_debug.o  += -Wno-packed
diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
new file mode 100644
index 0000000..988fef1
--- /dev/null
+++ b/tools/perf/util/c++/Build
@@ -0,0 +1,2 @@
+libperf-$(CONFIG_CLANGLLVM) += clang.o
+libperf-$(CONFIG_CLANGLLVM) += clang-test.o
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
new file mode 100644
index 0000000..dcde4b5
--- /dev/null
+++ b/tools/perf/util/c++/clang-c.h
@@ -0,0 +1,16 @@
+#ifndef PERF_UTIL_CLANG_C_H
+#define PERF_UTIL_CLANG_C_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void perf_clang__init(void);
+extern void perf_clang__cleanup(void);
+
+extern int test__clang_to_IR(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
new file mode 100644
index 0000000..3da6bfa
--- /dev/null
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -0,0 +1,31 @@
+#include "clang.h"
+#include "clang-c.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/LLVMContext.h"
+
+class perf_clang_scope {
+public:
+	explicit perf_clang_scope() {perf_clang__init();}
+	~perf_clang_scope() {perf_clang__cleanup();}
+};
+
+extern "C" {
+
+int test__clang_to_IR(void)
+{
+	perf_clang_scope _scope;
+
+	std::unique_ptr<llvm::Module> M =
+		perf::getModuleFromSource("perf-test.c",
+					  "int myfunc(void) {return 1;}");
+
+	if (!M)
+		return -1;
+
+	for (llvm::Function& F : *M)
+		if (F.getName() == "myfunc")
+			return 0;
+	return -1;
+}
+
+}
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
new file mode 100644
index 0000000..c17b117
--- /dev/null
+++ b/tools/perf/util/c++/clang.cpp
@@ -0,0 +1,96 @@
+/*
+ * llvm C frontend for perf. Support dynamically compile C file
+ *
+ * Inspired by clang example code:
+ * http://llvm.org/svn/llvm-project/cfe/trunk/examples/clang-interpreter/main.cpp
+ *
+ * Copyright (C) 2016 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2016 Huawei Inc.
+ */
+
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/ManagedStatic.h"
+#include <memory>
+
+#include "clang.h"
+#include "clang-c.h"
+
+namespace perf {
+
+static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
+
+using namespace clang;
+
+static vfs::InMemoryFileSystem *
+buildVFS(StringRef& Name, StringRef& Content)
+{
+	vfs::InMemoryFileSystem *VFS = new vfs::InMemoryFileSystem(true);
+	VFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
+	return VFS;
+}
+
+static CompilerInvocation *
+createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
+{
+	llvm::opt::ArgStringList CCArgs {
+		"-cc1",
+		"-triple", "bpf-pc-linux",
+		"-fsyntax-only",
+		"-ferror-limit", "19",
+		"-fmessage-length", "127",
+		"-O2",
+		"-nostdsysteminc",
+		"-nobuiltininc",
+		"-vectorize-loops",
+		"-vectorize-slp",
+		"-Wno-unused-value",
+		"-Wno-pointer-sign",
+		"-x", "c"};
+	CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);
+
+	FrontendOptions& Opts = CI->getFrontendOpts();
+	Opts.Inputs.clear();
+	Opts.Inputs.emplace_back(Path, IK_C);
+	return CI;
+}
+
+std::unique_ptr<llvm::Module>
+getModuleFromSource(StringRef Name, StringRef Content)
+{
+	CompilerInstance Clang;
+	Clang.createDiagnostics();
+
+	IntrusiveRefCntPtr<vfs::FileSystem> VFS = buildVFS(Name, Content);
+	Clang.setVirtualFileSystem(&*VFS);
+
+	IntrusiveRefCntPtr<CompilerInvocation> CI =
+		createCompilerInvocation(Name, Clang.getDiagnostics());
+	Clang.setInvocation(&*CI);
+
+	std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
+	if (!Clang.ExecuteAction(*Act))
+		return std::unique_ptr<llvm::Module>(nullptr);
+
+	return Act->takeModule();
+}
+
+}
+
+extern "C" {
+void perf_clang__init(void)
+{
+	perf::LLVMCtx.reset(new llvm::LLVMContext());
+}
+
+void perf_clang__cleanup(void)
+{
+	perf::LLVMCtx.reset(nullptr);
+	llvm::llvm_shutdown();
+}
+}
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
new file mode 100644
index 0000000..f64483b
--- /dev/null
+++ b/tools/perf/util/c++/clang.h
@@ -0,0 +1,16 @@
+#ifndef PERF_UTIL_CLANG_H
+#define PERF_UTIL_CLANG_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include <memory>
+namespace perf {
+
+using namespace llvm;
+
+std::unique_ptr<Module>
+getModuleFromSource(StringRef Name, StringRef Content);
+
+}
+#endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 11/30] perf clang: Use real file system for #include
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (9 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 10/30] perf clang: Add builtin clang support ant test case Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-12-06  8:24   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 12/30] perf clang: Allow passing CFLAGS to builtin clang Wang Nan
                   ` (18 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Utilize clang's OverlayFileSystem facility, allow CompilerInstance to
access real file system.

With this patch '#include' directive can be used.

Add a new getModuleFromSource for real file.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/c++/clang.cpp | 44 +++++++++++++++++++++++++++++++------------
 tools/perf/util/c++/clang.h   |  3 +++
 2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index c17b117..cf96199 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -15,6 +15,7 @@
 #include "clang/Tooling/Tooling.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Option/Option.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/ManagedStatic.h"
 #include <memory>
 
@@ -27,14 +28,6 @@ static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
 
 using namespace clang;
 
-static vfs::InMemoryFileSystem *
-buildVFS(StringRef& Name, StringRef& Content)
-{
-	vfs::InMemoryFileSystem *VFS = new vfs::InMemoryFileSystem(true);
-	VFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
-	return VFS;
-}
-
 static CompilerInvocation *
 createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
 {
@@ -60,17 +53,17 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
 	return CI;
 }
 
-std::unique_ptr<llvm::Module>
-getModuleFromSource(StringRef Name, StringRef Content)
+static std::unique_ptr<llvm::Module>
+getModuleFromSource(StringRef Path,
+		    IntrusiveRefCntPtr<vfs::FileSystem> VFS)
 {
 	CompilerInstance Clang;
 	Clang.createDiagnostics();
 
-	IntrusiveRefCntPtr<vfs::FileSystem> VFS = buildVFS(Name, Content);
 	Clang.setVirtualFileSystem(&*VFS);
 
 	IntrusiveRefCntPtr<CompilerInvocation> CI =
-		createCompilerInvocation(Name, Clang.getDiagnostics());
+		createCompilerInvocation(Path, Clang.getDiagnostics());
 	Clang.setInvocation(&*CI);
 
 	std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
@@ -80,6 +73,33 @@ getModuleFromSource(StringRef Name, StringRef Content)
 	return Act->takeModule();
 }
 
+std::unique_ptr<llvm::Module>
+getModuleFromSource(StringRef Name, StringRef Content)
+{
+	using namespace vfs;
+
+	llvm::IntrusiveRefCntPtr<OverlayFileSystem> OverlayFS(
+			new OverlayFileSystem(getRealFileSystem()));
+	llvm::IntrusiveRefCntPtr<InMemoryFileSystem> MemFS(
+			new InMemoryFileSystem(true));
+
+	/*
+	 * pushOverlay helps setting working dir for MemFS. Must call
+	 * before addFile.
+	 */
+	OverlayFS->pushOverlay(MemFS);
+	MemFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
+
+	return getModuleFromSource(Name, OverlayFS);
+}
+
+std::unique_ptr<llvm::Module>
+getModuleFromSource(StringRef Path)
+{
+	IntrusiveRefCntPtr<vfs::FileSystem> VFS(vfs::getRealFileSystem());
+	return getModuleFromSource(Path, VFS);
+}
+
 }
 
 extern "C" {
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index f64483b..90aff01 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -12,5 +12,8 @@ using namespace llvm;
 std::unique_ptr<Module>
 getModuleFromSource(StringRef Name, StringRef Content);
 
+std::unique_ptr<Module>
+getModuleFromSource(StringRef Path);
+
 }
 #endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 12/30] perf clang: Allow passing CFLAGS to builtin clang
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (10 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 11/30] perf clang: Use real file system for #include Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-12-06  8:25   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 13/30] perf clang: Update test case to use real BPF script Wang Nan
                   ` (17 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Improve getModuleFromSource() API to accept a cflags list. This feature
will be used to pass LINUX_VERSION_CODE and -I flags.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1474874832-134786-9-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/c++/clang-test.cpp |  5 +++--
 tools/perf/util/c++/clang.cpp      | 21 +++++++++++++--------
 tools/perf/util/c++/clang.h        |  8 ++++++--
 3 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
index 3da6bfa..0f484fb 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -16,8 +16,9 @@ int test__clang_to_IR(void)
 	perf_clang_scope _scope;
 
 	std::unique_ptr<llvm::Module> M =
-		perf::getModuleFromSource("perf-test.c",
-					  "int myfunc(void) {return 1;}");
+		perf::getModuleFromSource({"-DRESULT=1"},
+					  "perf-test.c",
+					  "int myfunc(void) {return RESULT;}");
 
 	if (!M)
 		return -1;
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index cf96199..715ca0a 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -29,7 +29,8 @@ static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
 using namespace clang;
 
 static CompilerInvocation *
-createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
+createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
+			 DiagnosticsEngine& Diags)
 {
 	llvm::opt::ArgStringList CCArgs {
 		"-cc1",
@@ -45,6 +46,8 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
 		"-Wno-unused-value",
 		"-Wno-pointer-sign",
 		"-x", "c"};
+
+	CCArgs.append(CFlags.begin(), CFlags.end());
 	CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);
 
 	FrontendOptions& Opts = CI->getFrontendOpts();
@@ -54,8 +57,8 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
 }
 
 static std::unique_ptr<llvm::Module>
-getModuleFromSource(StringRef Path,
-		    IntrusiveRefCntPtr<vfs::FileSystem> VFS)
+getModuleFromSource(llvm::opt::ArgStringList CFlags,
+		    StringRef Path, IntrusiveRefCntPtr<vfs::FileSystem> VFS)
 {
 	CompilerInstance Clang;
 	Clang.createDiagnostics();
@@ -63,7 +66,8 @@ getModuleFromSource(StringRef Path,
 	Clang.setVirtualFileSystem(&*VFS);
 
 	IntrusiveRefCntPtr<CompilerInvocation> CI =
-		createCompilerInvocation(Path, Clang.getDiagnostics());
+		createCompilerInvocation(std::move(CFlags), Path,
+					 Clang.getDiagnostics());
 	Clang.setInvocation(&*CI);
 
 	std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
@@ -74,7 +78,8 @@ getModuleFromSource(StringRef Path,
 }
 
 std::unique_ptr<llvm::Module>
-getModuleFromSource(StringRef Name, StringRef Content)
+getModuleFromSource(llvm::opt::ArgStringList CFlags,
+		    StringRef Name, StringRef Content)
 {
 	using namespace vfs;
 
@@ -90,14 +95,14 @@ getModuleFromSource(StringRef Name, StringRef Content)
 	OverlayFS->pushOverlay(MemFS);
 	MemFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
 
-	return getModuleFromSource(Name, OverlayFS);
+	return getModuleFromSource(std::move(CFlags), Name, OverlayFS);
 }
 
 std::unique_ptr<llvm::Module>
-getModuleFromSource(StringRef Path)
+getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
 {
 	IntrusiveRefCntPtr<vfs::FileSystem> VFS(vfs::getRealFileSystem());
-	return getModuleFromSource(Path, VFS);
+	return getModuleFromSource(std::move(CFlags), Path, VFS);
 }
 
 }
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index 90aff01..b4fc2a9 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -4,16 +4,20 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Option/Option.h"
 #include <memory>
+
 namespace perf {
 
 using namespace llvm;
 
 std::unique_ptr<Module>
-getModuleFromSource(StringRef Name, StringRef Content);
+getModuleFromSource(opt::ArgStringList CFlags,
+		    StringRef Name, StringRef Content);
 
 std::unique_ptr<Module>
-getModuleFromSource(StringRef Path);
+getModuleFromSource(opt::ArgStringList CFlags,
+		    StringRef Path);
 
 }
 #endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 13/30] perf clang: Update test case to use real BPF script
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (11 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 12/30] perf clang: Allow passing CFLAGS to builtin clang Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-12-06  8:25   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 14/30] perf clang: Support compile IR to BPF object and add testcase Wang Nan
                   ` (16 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Allow C++ code to use util.h and tests/llvm.h. Let 'perf test' compile a
real BPF script.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1474874832-134786-10-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Makefile.config         | 27 +++++++++++++++------------
 tools/perf/tests/llvm.h            |  7 +++++++
 tools/perf/util/c++/clang-test.cpp | 17 ++++++++++++++---
 tools/perf/util/util-cxx.h         | 26 ++++++++++++++++++++++++++
 4 files changed, 62 insertions(+), 15 deletions(-)
 create mode 100644 tools/perf/util/util-cxx.h

diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index b7c9c80..09c2a98 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -212,24 +212,27 @@ ifeq ($(DEBUG),0)
   endif
 endif
 
-CFLAGS += -I$(src-perf)/util/include
-CFLAGS += -I$(src-perf)/arch/$(ARCH)/include
-CFLAGS += -I$(srctree)/tools/include/uapi
-CFLAGS += -I$(srctree)/tools/include/
-CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
-CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
-CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/
+INC_FLAGS += -I$(src-perf)/util/include
+INC_FLAGS += -I$(src-perf)/arch/$(ARCH)/include
+INC_FLAGS += -I$(srctree)/tools/include/uapi
+INC_FLAGS += -I$(srctree)/tools/include/
+INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
+INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
+INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/
 
 # $(obj-perf)      for generated common-cmds.h
 # $(obj-perf)/util for generated bison/flex headers
 ifneq ($(OUTPUT),)
-CFLAGS += -I$(obj-perf)/util
-CFLAGS += -I$(obj-perf)
+INC_FLAGS += -I$(obj-perf)/util
+INC_FLAGS += -I$(obj-perf)
 endif
 
-CFLAGS += -I$(src-perf)/util
-CFLAGS += -I$(src-perf)
-CFLAGS += -I$(srctree)/tools/lib/
+INC_FLAGS += -I$(src-perf)/util
+INC_FLAGS += -I$(src-perf)
+INC_FLAGS += -I$(srctree)/tools/lib/
+
+CFLAGS   += $(INC_FLAGS)
+CXXFLAGS += $(INC_FLAGS)
 
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
index 0eaa604..b835717 100644
--- a/tools/perf/tests/llvm.h
+++ b/tools/perf/tests/llvm.h
@@ -1,6 +1,10 @@
 #ifndef PERF_TEST_LLVM_H
 #define PERF_TEST_LLVM_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include <stddef.h> /* for size_t */
 #include <stdbool.h> /* for bool */
 
@@ -20,4 +24,7 @@ enum test_llvm__testcase {
 int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz,
 			     enum test_llvm__testcase index, bool force,
 			     bool *should_load_fail);
+#ifdef __cplusplus
+}
+#endif
 #endif
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
index 0f484fb..d84e760 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -3,6 +3,10 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/LLVMContext.h"
 
+#include <util-cxx.h>
+#include <tests/llvm.h>
+#include <string>
+
 class perf_clang_scope {
 public:
 	explicit perf_clang_scope() {perf_clang__init();}
@@ -14,17 +18,24 @@ extern "C" {
 int test__clang_to_IR(void)
 {
 	perf_clang_scope _scope;
+	unsigned int kernel_version;
+
+	if (fetch_kernel_version(&kernel_version, NULL, 0))
+		return -1;
+
+	std::string cflag_kver("-DLINUX_VERSION_CODE=" +
+				std::to_string(kernel_version));
 
 	std::unique_ptr<llvm::Module> M =
-		perf::getModuleFromSource({"-DRESULT=1"},
+		perf::getModuleFromSource({cflag_kver.c_str()},
 					  "perf-test.c",
-					  "int myfunc(void) {return RESULT;}");
+					  test_llvm__bpf_base_prog);
 
 	if (!M)
 		return -1;
 
 	for (llvm::Function& F : *M)
-		if (F.getName() == "myfunc")
+		if (F.getName() == "bpf_func__SyS_epoll_wait")
 			return 0;
 	return -1;
 }
diff --git a/tools/perf/util/util-cxx.h b/tools/perf/util/util-cxx.h
new file mode 100644
index 0000000..0e0e019
--- /dev/null
+++ b/tools/perf/util/util-cxx.h
@@ -0,0 +1,26 @@
+/*
+ * Support C++ source use utilities defined in util.h
+ */
+
+#ifndef PERF_UTIL_UTIL_CXX_H
+#define PERF_UTIL_UTIL_CXX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Now 'new' is the only C++ keyword found in util.h:
+ * in tools/include/linux/rbtree.h
+ *
+ * Other keywords, like class and delete, should be
+ * redefined if necessary.
+ */
+#define new _new
+#include "util.h"
+#undef new
+
+#ifdef __cplusplus
+}
+#endif
+#endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 14/30] perf clang: Support compile IR to BPF object and add testcase
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (12 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 13/30] perf clang: Update test case to use real BPF script Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26 17:25   ` Alexei Starovoitov
  2016-12-06  8:26   ` [tip:perf/core] " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 15/30] perf clang: Compile BPF script use builtin clang support Wang Nan
                   ` (15 subsequent siblings)
  29 siblings, 2 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

getBPFObjectFromModule() is introduced to compile LLVM IR(Module)
to BPF object. Add new testcase for it.

Test result:
  $ ./buildperf/perf test -v clang
  51: Test builtin clang support                               :
  51.1: Test builtin clang compile C source to IR              :
  --- start ---
  test child forked, pid 21822
  test child finished with 0
  ---- end ----
  Test builtin clang support subtest 0: Ok
  51.2: Test builtin clang compile C source to ELF object      :
  --- start ---
  test child forked, pid 21823
  test child finished with 0
  ---- end ----
  Test builtin clang support subtest 1: Ok

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/tests/clang.c           |  6 ++++-
 tools/perf/util/c++/clang-c.h      |  1 +
 tools/perf/util/c++/clang-test.cpp | 31 +++++++++++++++++++++-----
 tools/perf/util/c++/clang.cpp      | 45 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/c++/clang.h        |  3 +++
 5 files changed, 79 insertions(+), 7 deletions(-)

diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
index 57ee160..2964c06 100644
--- a/tools/perf/tests/clang.c
+++ b/tools/perf/tests/clang.c
@@ -12,6 +12,10 @@ static struct {
 		.func = test__clang_to_IR,
 		.desc = "Test builtin clang compile C source to IR",
 	},
+	{
+		.func = test__clang_to_obj,
+		.desc = "Test builtin clang compile C source to ELF object",
+	},
 #endif
 };
 
@@ -33,7 +37,7 @@ int test__clang(int i __maybe_unused)
 	return TEST_SKIP;
 }
 #else
-int test__clang(int i __maybe_unused)
+int test__clang(int i)
 {
 	if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
 		return TEST_FAIL;
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index dcde4b5..22b3936 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -9,6 +9,7 @@ extern void perf_clang__init(void);
 extern void perf_clang__cleanup(void);
 
 extern int test__clang_to_IR(void);
+extern int test__clang_to_obj(void);
 
 #ifdef __cplusplus
 }
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
index d84e760..9b11e8c 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -13,15 +13,13 @@ public:
 	~perf_clang_scope() {perf_clang__cleanup();}
 };
 
-extern "C" {
-
-int test__clang_to_IR(void)
+static std::unique_ptr<llvm::Module>
+__test__clang_to_IR(void)
 {
-	perf_clang_scope _scope;
 	unsigned int kernel_version;
 
 	if (fetch_kernel_version(&kernel_version, NULL, 0))
-		return -1;
+		return std::unique_ptr<llvm::Module>(nullptr);
 
 	std::string cflag_kver("-DLINUX_VERSION_CODE=" +
 				std::to_string(kernel_version));
@@ -30,14 +28,35 @@ int test__clang_to_IR(void)
 		perf::getModuleFromSource({cflag_kver.c_str()},
 					  "perf-test.c",
 					  test_llvm__bpf_base_prog);
+	return M;
+}
+
+extern "C" {
+int test__clang_to_IR(void)
+{
+	perf_clang_scope _scope;
 
+	auto M = __test__clang_to_IR();
 	if (!M)
 		return -1;
-
 	for (llvm::Function& F : *M)
 		if (F.getName() == "bpf_func__SyS_epoll_wait")
 			return 0;
 	return -1;
 }
 
+int test__clang_to_obj(void)
+{
+	perf_clang_scope _scope;
+
+	auto M = __test__clang_to_IR();
+	if (!M)
+		return -1;
+
+	auto Buffer = perf::getBPFObjectFromModule(&*M);
+	if (!Buffer)
+		return -1;
+	return 0;
+}
+
 }
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 715ca0a..2a1a75d 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -13,10 +13,15 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
 #include <memory>
 
 #include "clang.h"
@@ -105,12 +110,52 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
 	return getModuleFromSource(std::move(CFlags), Path, VFS);
 }
 
+std::unique_ptr<llvm::SmallVectorImpl<char>>
+getBPFObjectFromModule(llvm::Module *Module)
+{
+	using namespace llvm;
+
+	std::string TargetTriple("bpf-pc-linux");
+	std::string Error;
+	const Target* Target = TargetRegistry::lookupTarget(TargetTriple, Error);
+	if (!Target) {
+		llvm::errs() << Error;
+		return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);
+	}
+
+	llvm::TargetOptions Opt;
+	TargetMachine *TargetMachine =
+		Target->createTargetMachine(TargetTriple,
+					    "generic", "",
+					    Opt, Reloc::Static);
+
+	Module->setDataLayout(TargetMachine->createDataLayout());
+	Module->setTargetTriple(TargetTriple);
+
+	std::unique_ptr<SmallVectorImpl<char>> Buffer(new SmallVector<char, 0>());
+	raw_svector_ostream ostream(*Buffer);
+
+	legacy::PassManager PM;
+	if (TargetMachine->addPassesToEmitFile(PM, ostream,
+					       TargetMachine::CGFT_ObjectFile)) {
+		llvm::errs() << "TargetMachine can't emit a file of this type\n";
+		return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);;
+	}
+	PM.run(*Module);
+
+	return std::move(Buffer);
+}
+
 }
 
 extern "C" {
 void perf_clang__init(void)
 {
 	perf::LLVMCtx.reset(new llvm::LLVMContext());
+	LLVMInitializeBPFTargetInfo();
+	LLVMInitializeBPFTarget();
+	LLVMInitializeBPFTargetMC();
+	LLVMInitializeBPFAsmPrinter();
 }
 
 void perf_clang__cleanup(void)
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index b4fc2a9..dd8b042 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -19,5 +19,8 @@ std::unique_ptr<Module>
 getModuleFromSource(opt::ArgStringList CFlags,
 		    StringRef Path);
 
+std::unique_ptr<llvm::SmallVectorImpl<char>>
+getBPFObjectFromModule(llvm::Module *Module);
+
 }
 #endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 15/30] perf clang: Compile BPF script use builtin clang support
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (13 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 14/30] perf clang: Support compile IR to BPF object and add testcase Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-12-06  8:26   ` [tip:perf/core] perf clang: Compile BPF script using " tip-bot for Wang Nan
  2016-11-26  7:03 ` [PATCH v3 16/30] perf clang: Pass full path to builtin clang Wang Nan
                   ` (14 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

After this patch, perf utilizes builtin clang support to build BPF
script, no longer depend on external clang.

Test:

  $ type clang
  -bash: type: clang: not found
  $ cat ~/.perfconfig
  $ echo '#define LINUX_VERSION_CODE 0x040700' > ./test.c
  $ cat ./tools/perf/tests/bpf-script-example.c >> ./test.c
  $ ./perf record -v --dry-run -e ./test.c 2>&1 | grep builtin
  bpf: builtin compiling successful

Can't pass cflags so unable to include kernel headers now. Will be fixed
by following commits.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1474874832-134786-13-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/bpf-loader.c  | 15 +++++++++++----
 tools/perf/util/c++/clang-c.h | 26 ++++++++++++++++++++++++++
 tools/perf/util/c++/clang.cpp | 29 +++++++++++++++++++++++++++++
 3 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index cf16b941..a0ea334f 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -14,11 +14,11 @@
 #include "debug.h"
 #include "bpf-loader.h"
 #include "bpf-prologue.h"
-#include "llvm-utils.h"
 #include "probe-event.h"
 #include "probe-finder.h" // for MAX_PROBES
 #include "parse-events.h"
 #include "llvm-utils.h"
+#include "c++/clang-c.h"
 
 #define DEFINE_PRINT_FN(name, level) \
 static int libbpf_##name(const char *fmt, ...)	\
@@ -86,9 +86,16 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 		void *obj_buf;
 		size_t obj_buf_sz;
 
-		err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
-		if (err)
-			return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+		perf_clang__init();
+		err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+		perf_clang__cleanup();
+		if (err) {
+			pr_warning("bpf: builtin compiling failed: %d, try external compiler\n", err);
+			err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+			if (err)
+				return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+		} else
+			pr_debug("bpf: builtin compiling successful\n");
 		obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
 
 		if (!IS_ERR(obj) && llvm_param.dump_obj)
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 22b3936..0eadd79 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -1,16 +1,42 @@
 #ifndef PERF_UTIL_CLANG_C_H
 #define PERF_UTIL_CLANG_C_H
 
+#include <stddef.h>	/* for size_t */
+#include <util-cxx.h>	/* for __maybe_unused */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#ifdef HAVE_LIBCLANGLLVM_SUPPORT
 extern void perf_clang__init(void);
 extern void perf_clang__cleanup(void);
 
 extern int test__clang_to_IR(void);
 extern int test__clang_to_obj(void);
 
+extern int perf_clang__compile_bpf(const char *filename,
+				   void **p_obj_buf,
+				   size_t *p_obj_buf_sz);
+#else
+
+
+static inline void perf_clang__init(void) { }
+static inline void perf_clang__cleanup(void) { }
+
+static inline int test__clang_to_IR(void) { return -1; }
+static inline int test__clang_to_obj(void) { return -1;}
+
+static inline int
+perf_clang__compile_bpf(const char *filename __maybe_unused,
+			void **p_obj_buf __maybe_unused,
+			size_t *p_obj_buf_sz __maybe_unused)
+{
+	return -ENOTSUP;
+}
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 2a1a75d..1e97415 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -163,4 +163,33 @@ void perf_clang__cleanup(void)
 	perf::LLVMCtx.reset(nullptr);
 	llvm::llvm_shutdown();
 }
+
+int perf_clang__compile_bpf(const char *filename,
+			    void **p_obj_buf,
+			    size_t *p_obj_buf_sz)
+{
+	using namespace perf;
+
+	if (!p_obj_buf || !p_obj_buf_sz)
+		return -EINVAL;
+
+	llvm::opt::ArgStringList CFlags;
+	auto M = getModuleFromSource(std::move(CFlags), filename);
+	if (!M)
+		return  -EINVAL;
+	auto O = getBPFObjectFromModule(&*M);
+	if (!O)
+		return -EINVAL;
+
+	size_t size = O->size_in_bytes();
+	void *buffer;
+
+	buffer = malloc(size);
+	if (!buffer)
+		return -ENOMEM;
+	memcpy(buffer, O->data(), size);
+	*p_obj_buf = buffer;
+	*p_obj_buf_sz = size;
+	return 0;
+}
 }
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 16/30] perf clang: Pass full path to builtin clang
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (14 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 15/30] perf clang: Compile BPF script use builtin clang support Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26  7:03 ` [PATCH v3 17/30] perf clang: Pass CFLAGS " Wang Nan
                   ` (13 subsequent siblings)
  29 siblings, 0 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

If clang changes its working directory, relative path passed to
perf_clang__compile_bpf() becomes invalid. Before running clang,
convert it to absolute path so file can be found even working directory
is changed.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/c++/clang.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 1e97415..610f1cf 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -13,6 +13,7 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Option/Option.h"
@@ -164,7 +165,7 @@ void perf_clang__cleanup(void)
 	llvm::llvm_shutdown();
 }
 
-int perf_clang__compile_bpf(const char *filename,
+int perf_clang__compile_bpf(const char *_filename,
 			    void **p_obj_buf,
 			    size_t *p_obj_buf_sz)
 {
@@ -173,8 +174,11 @@ int perf_clang__compile_bpf(const char *filename,
 	if (!p_obj_buf || !p_obj_buf_sz)
 		return -EINVAL;
 
+	llvm::SmallString<PATH_MAX> FileName(_filename);
+	llvm::sys::fs::make_absolute(FileName);
+
 	llvm::opt::ArgStringList CFlags;
-	auto M = getModuleFromSource(std::move(CFlags), filename);
+	auto M = getModuleFromSource(std::move(CFlags), FileName.data());
 	if (!M)
 		return  -EINVAL;
 	auto O = getBPFObjectFromModule(&*M);
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 17/30] perf clang: Pass CFLAGS to builtin clang
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (15 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 16/30] perf clang: Pass full path to builtin clang Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26  7:03 ` [PATCH v3 18/30] perf clang jit: Wrap llvm::Module using PerfModule Wang Nan
                   ` (12 subsequent siblings)
  29 siblings, 0 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Pass -DLINUX_VERSION_CODE, -D__NR_CPUS__, llvm.clang-opt config options
and CFLAGS detected by kbuild detector to builtin clang so BPF scripts
can use kernel headers and user defined options like external clang
compiler.

Test:
  # perf record -v --dry-run -e tools/perf/tests/bpf-script-test-kbuild.c ls 2>&1 | grep built
  bpf: builtin compiling successful

Committer notes:

Before installing the required clang/llvm devel files to have it
builtin:

  # perf record -v --dry-run -e tools/perf/tests/bpf-script-test-kbuild.c ls 2>&1 | grep built
  bpf: builtin compiling failed: -95, try external compiler

I.e. it falls back to using the external compiler.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/c++/clang.cpp | 105 ++++++++++++++++++++++++++++++++++++++++--
 tools/perf/util/llvm-utils.h  |   9 +++-
 2 files changed, 109 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 610f1cf..3a3b9791 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -27,6 +27,8 @@
 
 #include "clang.h"
 #include "clang-c.h"
+#include "llvm-utils.h"
+#include "util-cxx.h"
 
 namespace perf {
 
@@ -147,6 +149,101 @@ getBPFObjectFromModule(llvm::Module *Module)
 	return std::move(Buffer);
 }
 
+class ClangOptions {
+	llvm::SmallString<PATH_MAX> FileName;
+	llvm::SmallString<64> KVerDef;
+	llvm::SmallString<64> NRCpusDef;
+	char *kbuild_dir;
+	char *kbuild_include_opts;
+	char *clang_opt;
+public:
+	ClangOptions(const char *filename) : FileName(filename),
+					     KVerDef(""),
+					     NRCpusDef(""),
+					     kbuild_dir(NULL),
+					     kbuild_include_opts(NULL),
+					     clang_opt(NULL)
+	{
+		llvm::sys::fs::make_absolute(FileName);
+
+		unsigned int kver;
+		if (!fetch_kernel_version(&kver, NULL, 0))
+			KVerDef = "-DLINUX_VERSION_CODE=" + std::to_string(kver);
+
+		int nr_cpus = llvm__get_nr_cpus();
+		if (nr_cpus > 0)
+			NRCpusDef = "-D__NR_CPUS__=" + std::to_string(nr_cpus);
+
+		if (llvm_param.clang_opt)
+			clang_opt = strdup(llvm_param.clang_opt);
+
+		llvm__get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
+		if (!kbuild_dir || !kbuild_include_opts) {
+			free(kbuild_dir);
+			free(kbuild_include_opts);
+			kbuild_dir = kbuild_include_opts = NULL;
+		}
+	}
+
+	~ClangOptions()
+	{
+		free(kbuild_dir);
+		free(kbuild_include_opts);
+		free(clang_opt);
+	}
+
+	static void fillCFlagsFromString(opt::ArgStringList &CFlags, char *s, bool check = false)
+	{
+		if (!s)
+			return;
+
+		SmallVector<StringRef, 0> Terms;
+		StringRef Opts(s);
+		Opts.split(Terms, ' ');
+
+		for (auto i = Terms.begin(); i != Terms.end(); i++)
+			s[i->end() - Opts.begin()] = '\0';
+
+		for (auto i = Terms.begin(); i != Terms.end(); i++) {
+			if (!check) {
+				CFlags.push_back(i->begin());
+				continue;
+			}
+
+			if (i->startswith("-I"))
+				CFlags.push_back(i->begin());
+			else if (i->startswith("-D"))
+				CFlags.push_back(i->begin());
+			else if (*i == "-include") {
+				CFlags.push_back((i++)->begin());
+				/* Let clang report this error */
+				if (i == Terms.end())
+					break;
+				CFlags.push_back(i->begin());
+			}
+		}
+	}
+
+	void getCFlags(opt::ArgStringList &CFlags)
+	{
+		CFlags.push_back(KVerDef.c_str());
+		CFlags.push_back(NRCpusDef.c_str());
+
+		fillCFlagsFromString(CFlags, clang_opt);
+		fillCFlagsFromString(CFlags, kbuild_include_opts, true);
+
+		if (kbuild_dir) {
+			CFlags.push_back("-working-directory");
+			CFlags.push_back(kbuild_dir);
+		}
+	}
+
+	const char *getFileName(void)
+	{
+		return FileName.c_str();
+	}
+};
+
 }
 
 extern "C" {
@@ -174,11 +271,11 @@ int perf_clang__compile_bpf(const char *_filename,
 	if (!p_obj_buf || !p_obj_buf_sz)
 		return -EINVAL;
 
-	llvm::SmallString<PATH_MAX> FileName(_filename);
-	llvm::sys::fs::make_absolute(FileName);
-
+	ClangOptions Opts(_filename);
 	llvm::opt::ArgStringList CFlags;
-	auto M = getModuleFromSource(std::move(CFlags), FileName.data());
+
+	Opts.getCFlags(CFlags);
+	auto M = getModuleFromSource(std::move(CFlags), Opts.getFileName());
 	if (!M)
 		return  -EINVAL;
 	auto O = getBPFObjectFromModule(&*M);
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h
index c87a2a9..263a00d 100644
--- a/tools/perf/util/llvm-utils.h
+++ b/tools/perf/util/llvm-utils.h
@@ -5,7 +5,11 @@
 #ifndef __LLVM_UTILS_H
 #define __LLVM_UTILS_H
 
-#include "debug.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <errno.h>
 
 struct llvm_param {
 	/* Path of clang executable */
@@ -56,4 +60,7 @@ void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts);
 int llvm__get_nr_cpus(void);
 
 void llvm__dump_obj(const char *path, void *obj_buf, size_t size);
+#ifdef __cplusplus
+}
+#endif
 #endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 18/30] perf clang jit: Wrap llvm::Module using PerfModule
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (16 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 17/30] perf clang: Pass CFLAGS " Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26  7:03 ` [PATCH v3 19/30] perf clang jit: Insignt BPF and JIT functions in a Module Wang Nan
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Use PerfModule wrap llvm::Module and return perf::PerfModule in APIs to
replace llvm::Module. Following commits are going to add new functions
to PerfModule.

getBPFObjectFromModule is merged to a method of perf::PerfModule.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/c++/clang-test.cpp | 10 +++++-----
 tools/perf/util/c++/clang.cpp      | 20 +++++++++++++-------
 tools/perf/util/c++/clang.h        | 22 ++++++++++++++++------
 3 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
index 9b11e8c..fb05e56 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -13,18 +13,18 @@ public:
 	~perf_clang_scope() {perf_clang__cleanup();}
 };
 
-static std::unique_ptr<llvm::Module>
+static std::unique_ptr<perf::PerfModule>
 __test__clang_to_IR(void)
 {
 	unsigned int kernel_version;
 
 	if (fetch_kernel_version(&kernel_version, NULL, 0))
-		return std::unique_ptr<llvm::Module>(nullptr);
+		return std::unique_ptr<perf::PerfModule>(nullptr);
 
 	std::string cflag_kver("-DLINUX_VERSION_CODE=" +
 				std::to_string(kernel_version));
 
-	std::unique_ptr<llvm::Module> M =
+	std::unique_ptr<perf::PerfModule> M =
 		perf::getModuleFromSource({cflag_kver.c_str()},
 					  "perf-test.c",
 					  test_llvm__bpf_base_prog);
@@ -39,7 +39,7 @@ int test__clang_to_IR(void)
 	auto M = __test__clang_to_IR();
 	if (!M)
 		return -1;
-	for (llvm::Function& F : *M)
+	for (llvm::Function& F : *(M->getModule()))
 		if (F.getName() == "bpf_func__SyS_epoll_wait")
 			return 0;
 	return -1;
@@ -53,7 +53,7 @@ int test__clang_to_obj(void)
 	if (!M)
 		return -1;
 
-	auto Buffer = perf::getBPFObjectFromModule(&*M);
+	auto Buffer = M->toBPFObject();
 	if (!Buffer)
 		return -1;
 	return 0;
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 3a3b9791..d31b0a5 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -64,7 +64,7 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
 	return CI;
 }
 
-static std::unique_ptr<llvm::Module>
+static std::unique_ptr<PerfModule>
 getModuleFromSource(llvm::opt::ArgStringList CFlags,
 		    StringRef Path, IntrusiveRefCntPtr<vfs::FileSystem> VFS)
 {
@@ -80,12 +80,12 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags,
 
 	std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
 	if (!Clang.ExecuteAction(*Act))
-		return std::unique_ptr<llvm::Module>(nullptr);
+		return std::unique_ptr<PerfModule>(nullptr);
 
-	return Act->takeModule();
+	return std::unique_ptr<PerfModule>(new PerfModule(std::move(Act->takeModule())));
 }
 
-std::unique_ptr<llvm::Module>
+std::unique_ptr<PerfModule>
 getModuleFromSource(llvm::opt::ArgStringList CFlags,
 		    StringRef Name, StringRef Content)
 {
@@ -106,15 +106,21 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags,
 	return getModuleFromSource(std::move(CFlags), Name, OverlayFS);
 }
 
-std::unique_ptr<llvm::Module>
+std::unique_ptr<PerfModule>
 getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
 {
 	IntrusiveRefCntPtr<vfs::FileSystem> VFS(vfs::getRealFileSystem());
 	return getModuleFromSource(std::move(CFlags), Path, VFS);
 }
 
+PerfModule::PerfModule(std::unique_ptr<llvm::Module>&& M) : Module(std::move(M))
+{
+
+}
+
+
 std::unique_ptr<llvm::SmallVectorImpl<char>>
-getBPFObjectFromModule(llvm::Module *Module)
+PerfModule::toBPFObject(void)
 {
 	using namespace llvm;
 
@@ -278,7 +284,7 @@ int perf_clang__compile_bpf(const char *_filename,
 	auto M = getModuleFromSource(std::move(CFlags), Opts.getFileName());
 	if (!M)
 		return  -EINVAL;
-	auto O = getBPFObjectFromModule(&*M);
+	auto O = M->toBPFObject();
 	if (!O)
 		return -EINVAL;
 
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index dd8b042..cbb291b 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -11,16 +11,26 @@ namespace perf {
 
 using namespace llvm;
 
-std::unique_ptr<Module>
+class PerfModule {
+private:
+	std::unique_ptr<llvm::Module> Module;
+public:
+	inline llvm::Module *getModule(void)
+	{
+		return Module.get();
+	}
+
+	PerfModule(std::unique_ptr<llvm::Module>&& M);
+
+	std::unique_ptr<llvm::SmallVectorImpl<char>> toBPFObject(void);
+};
+
+std::unique_ptr<PerfModule>
 getModuleFromSource(opt::ArgStringList CFlags,
 		    StringRef Name, StringRef Content);
 
-std::unique_ptr<Module>
+std::unique_ptr<PerfModule>
 getModuleFromSource(opt::ArgStringList CFlags,
 		    StringRef Path);
-
-std::unique_ptr<llvm::SmallVectorImpl<char>>
-getBPFObjectFromModule(llvm::Module *Module);
-
 }
 #endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 19/30] perf clang jit: Insignt BPF and JIT functions in a Module
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (17 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 18/30] perf clang jit: Wrap llvm::Module using PerfModule Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26 17:32   ` Alexei Starovoitov
  2016-11-26  7:03 ` [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions Wang Nan
                   ` (10 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Identify BPF functions, JIT functions and maps during init. Functions in
section starting with "perfhook:" are JIT functions. They will be JIT
compiled and hooked at perfhooks.

During init of PerfModule, mark JIT functions as AvailableExternallyLinkage.
LLVM skips functions with linkage like this so they won't be compiled
into BPF objects.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/c++/clang.cpp | 32 ++++++++++++++++++++++++++++++++
 tools/perf/util/c++/clang.h   |  7 +++++++
 2 files changed, 39 insertions(+)

diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index d31b0a5..98d05e2 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -115,15 +115,47 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
 
 PerfModule::PerfModule(std::unique_ptr<llvm::Module>&& M) : Module(std::move(M))
 {
+	for (llvm::Function& F : *Module) {
+		if (F.getLinkage() != llvm::GlobalValue::ExternalLinkage)
+			continue;
+
+		if (StringRef(F.getSection()).startswith("perfhook:"))
+			JITFunctions.insert(&F);
+		else
+			BPFFunctions.insert(&F);
+	}
 
+	for (auto V = Module->global_begin(); V != Module->global_end(); V++) {
+		llvm::GlobalVariable *GV = &*V;
+		if (StringRef(GV->getSection()) == llvm::StringRef("maps"))
+			Maps.insert(GV);
+	}
 }
 
+void PerfModule::prepareBPF(void)
+{
+	for (llvm::Function *F : JITFunctions)
+		F->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
+	for (llvm::Function *F : BPFFunctions)
+		F->setLinkage(llvm::GlobalValue::ExternalLinkage);
+
+}
+
+void PerfModule::prepareJIT(void)
+{
+	for (llvm::Function *F : BPFFunctions)
+		F->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
+	for (llvm::Function *F : JITFunctions)
+		F->setLinkage(llvm::GlobalValue::ExternalLinkage);
+
+}
 
 std::unique_ptr<llvm::SmallVectorImpl<char>>
 PerfModule::toBPFObject(void)
 {
 	using namespace llvm;
 
+	prepareBPF();
 	std::string TargetTriple("bpf-pc-linux");
 	std::string Error;
 	const Target* Target = TargetRegistry::lookupTarget(TargetTriple, Error);
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index cbb291b..1eb71a6 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -6,6 +6,7 @@
 #include "llvm/IR/Module.h"
 #include "llvm/Option/Option.h"
 #include <memory>
+#include <set>
 
 namespace perf {
 
@@ -14,6 +15,12 @@ using namespace llvm;
 class PerfModule {
 private:
 	std::unique_ptr<llvm::Module> Module;
+
+	std::set<llvm::GlobalVariable *> Maps;
+	std::set<llvm::Function *> BPFFunctions;
+	std::set<llvm::Function *> JITFunctions;
+	void prepareBPF(void);
+	void prepareJIT(void);
 public:
 	inline llvm::Module *getModule(void)
 	{
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (18 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 19/30] perf clang jit: Insignt BPF and JIT functions in a Module Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26 17:29   ` Alexei Starovoitov
  2016-11-26  7:03 ` [PATCH v3 21/30] perf clang jit: Export functions for jitted code Wang Nan
                   ` (9 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

PerfModule::doJIT JIT compile perfhook functions and saves result into
a map. Add a test case for it.

At this stage perfhook functions can do no useful things because they
can't invoke external functions and can't return value. Following
commits are going to make improvment.

Don't hook functions right after jitted because bpf_object is unavailable
during jitting but it should be the context of jitted functions.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/tests/bpf-script-example.c |  8 ++++
 tools/perf/tests/clang.c              |  4 ++
 tools/perf/util/c++/clang-c.h         |  2 +
 tools/perf/util/c++/clang-test.cpp    | 32 +++++++++++++++-
 tools/perf/util/c++/clang.cpp         | 71 +++++++++++++++++++++++++++++++++++
 tools/perf/util/c++/clang.h           | 13 +++++++
 6 files changed, 128 insertions(+), 2 deletions(-)

diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
index 268e5f8..265036e 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -46,3 +46,11 @@ int bpf_func__SyS_epoll_wait(void *ctx)
 }
 char _license[] SEC("license") = "GPL";
 int _version SEC("version") = LINUX_VERSION_CODE;
+
+#ifdef TEST_PERF_HOOK
+SEC("perfhook:test")
+void hook_test(void)
+{
+	return;
+}
+#endif
diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
index 2964c06..f274e62 100644
--- a/tools/perf/tests/clang.c
+++ b/tools/perf/tests/clang.c
@@ -16,6 +16,10 @@ static struct {
 		.func = test__clang_to_obj,
 		.desc = "Test builtin clang compile C source to ELF object",
 	},
+	{
+		.func = test__clang_jit,
+		.desc = "Test builtin clang compile mixed BPF and native code",
+	},
 #endif
 };
 
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 0eadd79..5ebcb41 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -14,6 +14,7 @@ extern void perf_clang__cleanup(void);
 
 extern int test__clang_to_IR(void);
 extern int test__clang_to_obj(void);
+extern int test__clang_jit(void);
 
 extern int perf_clang__compile_bpf(const char *filename,
 				   void **p_obj_buf,
@@ -26,6 +27,7 @@ static inline void perf_clang__cleanup(void) { }
 
 static inline int test__clang_to_IR(void) { return -1; }
 static inline int test__clang_to_obj(void) { return -1;}
+static inline int test__clang_jit(void) { return -1;}
 
 static inline int
 perf_clang__compile_bpf(const char *filename __maybe_unused,
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
index fb05e56..2b4aa8d 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -5,6 +5,7 @@
 
 #include <util-cxx.h>
 #include <tests/llvm.h>
+#include <perf-hooks.h>
 #include <string>
 
 class perf_clang_scope {
@@ -14,7 +15,7 @@ public:
 };
 
 static std::unique_ptr<perf::PerfModule>
-__test__clang_to_IR(void)
+__test__clang_to_IR(bool perfhook)
 {
 	unsigned int kernel_version;
 
@@ -23,14 +24,22 @@ __test__clang_to_IR(void)
 
 	std::string cflag_kver("-DLINUX_VERSION_CODE=" +
 				std::to_string(kernel_version));
+	std::string cflag_perfhook(perfhook ? "-DTEST_PERF_HOOK=1" : "");
 
 	std::unique_ptr<perf::PerfModule> M =
-		perf::getModuleFromSource({cflag_kver.c_str()},
+		perf::getModuleFromSource({cflag_kver.c_str(),
+					   cflag_perfhook.c_str()},
 					  "perf-test.c",
 					  test_llvm__bpf_base_prog);
 	return M;
 }
 
+static std::unique_ptr<perf::PerfModule>
+__test__clang_to_IR(void)
+{
+	return __test__clang_to_IR(false);
+}
+
 extern "C" {
 int test__clang_to_IR(void)
 {
@@ -59,4 +68,23 @@ int test__clang_to_obj(void)
 	return 0;
 }
 
+int test__clang_jit(void)
+{
+	perf_clang_scope _scope;
+
+	auto M = __test__clang_to_IR(true);
+	if (!M)
+		return -1;
+
+	if (M->doJIT())
+		return -1;
+
+	std::unique_ptr<perf::PerfModule::HookMap> hooks(M->copyJITResult());
+	for (auto i : *hooks)
+		perf_hooks__set_hook(i.first.c_str(), i.second, NULL);
+
+	perf_hooks__invoke_test();
+	return 0;
+}
+
 }
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 98d05e2..03012b2 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -14,9 +14,14 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Option/Option.h"
+#include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/TargetRegistry.h"
@@ -24,11 +29,13 @@
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
 #include <memory>
+#include <vector>
 
 #include "clang.h"
 #include "clang-c.h"
 #include "llvm-utils.h"
 #include "util-cxx.h"
+#include "perf-hooks.h"
 
 namespace perf {
 
@@ -187,6 +194,66 @@ PerfModule::toBPFObject(void)
 	return std::move(Buffer);
 }
 
+/*
+ * Use a global memory manager so allocated code and data won't be released
+ * when object destroy.
+ */
+static llvm::SectionMemoryManager JITMemoryManager;
+
+int PerfModule::doJIT(void)
+{
+	using namespace orc;
+
+	prepareJIT();
+
+	std::unique_ptr<TargetMachine> TM(EngineBuilder().selectTarget());
+	if (!TM) {
+		llvm::errs() << "Can't get target machine\n";
+		return -1;
+	}
+	const DataLayout DL(TM->createDataLayout());
+	Module->setDataLayout(DL);
+	Module->setTargetTriple(TM->getTargetTriple().normalize());
+
+	ObjectLinkingLayer<> ObjectLayer;
+	IRCompileLayer<decltype(ObjectLayer)> CompileLayer(ObjectLayer, SimpleCompiler(*TM));
+
+	auto Resolver = createLambdaResolver(
+			[](const std::string &Name) {
+				return RuntimeDyld::SymbolInfo(nullptr);
+			},
+			[](const std::string &Name) {
+				return RuntimeDyld::SymbolInfo(nullptr);
+			});
+
+	std::vector<llvm::Module *> Ms;
+	Ms.push_back(getModule());
+	CompileLayer.addModuleSet(std::move(Ms),
+			&JITMemoryManager,
+			std::move(Resolver));
+
+
+	for (Function *F : JITFunctions) {
+		JITSymbol sym = CompileLayer.findSymbol(F->getName().str(), true);
+
+		/*
+		 * Type of F->getSection() is moving from
+		 * const char * to StringRef.
+		 * Convert it to std::string so we don't need
+		 * consider this API change.
+		 */
+		std::string sec(F->getSection());
+		std::string hook(&sec.c_str()[sizeof("perfhook:") - 1]);
+		perf_hook_func_t func = (perf_hook_func_t)(intptr_t)sym.getAddress();
+
+		if (JITResult[hook])
+			llvm::errs() << "Warning: multiple functions on hook "
+				     << hook << ", only one is used\n";
+		JITResult[hook] = func;
+	}
+	return 0;
+}
+
 class ClangOptions {
 	llvm::SmallString<PATH_MAX> FileName;
 	llvm::SmallString<64> KVerDef;
@@ -292,6 +359,10 @@ void perf_clang__init(void)
 	LLVMInitializeBPFTarget();
 	LLVMInitializeBPFTargetMC();
 	LLVMInitializeBPFAsmPrinter();
+
+	llvm::InitializeNativeTarget();
+	llvm::InitializeNativeTargetAsmPrinter();
+	llvm::InitializeNativeTargetAsmParser();
 }
 
 void perf_clang__cleanup(void)
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index 1eb71a6..df2eb8f 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -7,18 +7,26 @@
 #include "llvm/Option/Option.h"
 #include <memory>
 #include <set>
+#include <map>
+
+#include "util/perf-hooks.h"
 
 namespace perf {
 
 using namespace llvm;
 
 class PerfModule {
+public:
+	typedef std::map<std::string, perf_hook_func_t> HookMap;
 private:
 	std::unique_ptr<llvm::Module> Module;
 
 	std::set<llvm::GlobalVariable *> Maps;
 	std::set<llvm::Function *> BPFFunctions;
 	std::set<llvm::Function *> JITFunctions;
+
+	HookMap JITResult;
+
 	void prepareBPF(void);
 	void prepareJIT(void);
 public:
@@ -26,10 +34,15 @@ class PerfModule {
 	{
 		return Module.get();
 	}
+	inline HookMap *copyJITResult(void)
+	{
+		return new HookMap(JITResult);
+	}
 
 	PerfModule(std::unique_ptr<llvm::Module>&& M);
 
 	std::unique_ptr<llvm::SmallVectorImpl<char>> toBPFObject(void);
+	int doJIT(void);
 };
 
 std::unique_ptr<PerfModule>
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 21/30] perf clang jit: Export functions for jitted code
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (19 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26  7:03 ` [PATCH v3 22/30] perf clang jit: Actually JIT and hook in bpf loader Wang Nan
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

After this patch functions attached on perf hooks is allowed to invoke
external functions. Add a testcase for this feature.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/tests/Build                |  2 +-
 tools/perf/tests/bpf-script-example.c |  4 ++++
 tools/perf/util/c++/clang-c.h         |  2 ++
 tools/perf/util/c++/clang-test.cpp    |  9 +++++++++
 tools/perf/util/c++/clang.cpp         | 17 ++++++++++++++++-
 5 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 6676c2d..d6e6e00 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -49,7 +49,7 @@ $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
 	$(call rule_mkdir)
 	$(Q)echo '#include <tests/llvm.h>' > $@
 	$(Q)echo 'const char test_llvm__bpf_base_prog[] =' >> $@
-	$(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
+	$(Q)sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
 	$(Q)echo ';' >> $@
 
 $(OUTPUT)tests/llvm-src-kbuild.c: tests/bpf-script-test-kbuild.c tests/Build
diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
index 265036e..ccbc19c 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -48,9 +48,13 @@ char _license[] SEC("license") = "GPL";
 int _version SEC("version") = LINUX_VERSION_CODE;
 
 #ifdef TEST_PERF_HOOK
+extern int printf(const char *fmt, ...);
+extern void test__clang_callback(int x);
 SEC("perfhook:test")
 void hook_test(void)
 {
+	printf("Hello, hook_test\n");
+	test__clang_callback(1234);
 	return;
 }
 #endif
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 5ebcb41..9f75e41 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -16,6 +16,8 @@ extern int test__clang_to_IR(void);
 extern int test__clang_to_obj(void);
 extern int test__clang_jit(void);
 
+extern void test__clang_callback(int x);
+
 extern int perf_clang__compile_bpf(const char *filename,
 				   void **p_obj_buf,
 				   size_t *p_obj_buf_sz);
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
index 2b4aa8d..0bdb807 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -68,6 +68,13 @@ int test__clang_to_obj(void)
 	return 0;
 }
 
+static int callback_flag;
+
+void test__clang_callback(int x)
+{
+	callback_flag = x;
+}
+
 int test__clang_jit(void)
 {
 	perf_clang_scope _scope;
@@ -84,6 +91,8 @@ int test__clang_jit(void)
 		perf_hooks__set_hook(i.first.c_str(), i.second, NULL);
 
 	perf_hooks__invoke_test();
+	if (callback_flag != 1234)
+		return -1;
 	return 0;
 }
 
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 03012b2..325fbe4 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -30,6 +30,8 @@
 #include "llvm/Target/TargetOptions.h"
 #include <memory>
 #include <vector>
+#include <set>
+#include <tuple>
 
 #include "clang.h"
 #include "clang-c.h"
@@ -194,6 +196,15 @@ PerfModule::toBPFObject(void)
 	return std::move(Buffer);
 }
 
+static std::map<const std::string, const void *> exported_funcs =
+{
+#define EXPORT(f) {#f, (const void *)&f}
+	EXPORT(test__clang_callback),
+	EXPORT(printf),
+	EXPORT(puts),
+#undef EXPORT
+};
+
 /*
  * Use a global memory manager so allocated code and data won't be released
  * when object destroy.
@@ -220,7 +231,11 @@ int PerfModule::doJIT(void)
 
 	auto Resolver = createLambdaResolver(
 			[](const std::string &Name) {
-				return RuntimeDyld::SymbolInfo(nullptr);
+				auto i = exported_funcs.find(Name);
+				if (i == exported_funcs.end())
+					return RuntimeDyld::SymbolInfo(nullptr);
+				return RuntimeDyld::SymbolInfo((uint64_t)(i->second),
+							       JITSymbolFlags::Exported);
 			},
 			[](const std::string &Name) {
 				return RuntimeDyld::SymbolInfo(nullptr);
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 22/30] perf clang jit: Actually JIT and hook in bpf loader
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (20 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 21/30] perf clang jit: Export functions for jitted code Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26  7:03 ` [PATCH v3 23/30] perf clang jit: Collect the lowest address in maps section as map_base Wang Nan
                   ` (7 subsequent siblings)
  29 siblings, 0 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Makes perf_clang__compile_bpf() actually uses clang jit to compile perf
hooks. Returns a map through perf_clang__compile_bpf(), and set hooks
after bpf_object is created.

After this path jitting takes actions for bpf loader. For example:
  $ cat ./test.c
  /******************************************************/
  #define SEC(name) __attribute__((section(name), used))
  SEC("dofork=_do_fork")
  int dofork(void *ctx)
  {
      return 0;
  }
  extern int printf(const char *fmt, ...);
  SEC("perfhook:record_start")
  void record_start(void)
  {
      printf("Welcom to perf record\n");
  }
  SEC("perfhook:record_end")
  void record_end(void)
  {
      printf("Goodbye, perf record\n");
  }
  char _license[] SEC("license") = "GPL";
  int _version SEC("version") = LINUX_VERSION_CODE;
  /******************************************************/
  $ perf record -e ./test.c sleep 1
  Welcom to perf record
  [ perf record: Woken up 1 times to write data ]
  Goodbye, perf record
  [ perf record: Captured and wrote 0.014 MB perf.data ]

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/bpf-loader.c  | 11 ++++++++++-
 tools/perf/util/c++/clang-c.h | 18 ++++++++++++++++--
 tools/perf/util/c++/clang.cpp | 28 +++++++++++++++++++++++++++-
 3 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index a0ea334f..e50045f 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -85,9 +85,11 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 		int err;
 		void *obj_buf;
 		size_t obj_buf_sz;
+		jitted_funcs_map_t jitted_funcs_map;
 
 		perf_clang__init();
-		err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+		err = perf_clang__compile_bpf(filename, &obj_buf,
+					      &obj_buf_sz, &jitted_funcs_map);
 		perf_clang__cleanup();
 		if (err) {
 			pr_warning("bpf: builtin compiling failed: %d, try external compiler\n", err);
@@ -101,6 +103,13 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 		if (!IS_ERR(obj) && llvm_param.dump_obj)
 			llvm__dump_obj(filename, obj_buf, obj_buf_sz);
 
+		/*
+		 * Call perf_clang__hook_jitted_func even IS_ERR(obj) to make sure
+		 * the C++ map pointer is deleted.
+		 */
+		if (jitted_funcs_map)
+			perf_clang__hook_jitted_func(jitted_funcs_map, obj, IS_ERR(obj));
+
 		free(obj_buf);
 	} else
 		obj = bpf_object__open(filename);
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 9f75e41..021b1ad 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -8,6 +8,7 @@
 extern "C" {
 #endif
 
+typedef void *jitted_funcs_map_t;
 #ifdef HAVE_LIBCLANGLLVM_SUPPORT
 extern void perf_clang__init(void);
 extern void perf_clang__cleanup(void);
@@ -20,7 +21,11 @@ extern void test__clang_callback(int x);
 
 extern int perf_clang__compile_bpf(const char *filename,
 				   void **p_obj_buf,
-				   size_t *p_obj_buf_sz);
+				   size_t *p_obj_buf_sz,
+				   jitted_funcs_map_t *p_funcs_map);
+
+extern int
+perf_clang__hook_jitted_func(jitted_funcs_map_t map, void *ctx, bool is_err);
 #else
 
 
@@ -34,7 +39,16 @@ static inline int test__clang_jit(void) { return -1;}
 static inline int
 perf_clang__compile_bpf(const char *filename __maybe_unused,
 			void **p_obj_buf __maybe_unused,
-			size_t *p_obj_buf_sz __maybe_unused)
+			size_t *p_obj_buf_sz __maybe_unused,
+			jitted_funcs_map_t *p_funcs_map __maybe_unused)
+{
+	return -ENOTSUP;
+}
+
+static inline int
+perf_clang__hook_jitted_func(jitted_funcs_map_t map __maybe_unused,
+			     void *ctx __maybe_unused,
+			     bool is_err __maybe_unused)
 {
 	return -ENOTSUP;
 }
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 325fbe4..f2608f5 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -388,7 +388,8 @@ void perf_clang__cleanup(void)
 
 int perf_clang__compile_bpf(const char *_filename,
 			    void **p_obj_buf,
-			    size_t *p_obj_buf_sz)
+			    size_t *p_obj_buf_sz,
+			    jitted_funcs_map_t *p_funcs_map)
 {
 	using namespace perf;
 
@@ -415,6 +416,31 @@ int perf_clang__compile_bpf(const char *_filename,
 	memcpy(buffer, O->data(), size);
 	*p_obj_buf = buffer;
 	*p_obj_buf_sz = size;
+
+	if (M->doJIT())
+		return -1;
+
+	if (p_funcs_map)
+		*p_funcs_map = (jitted_funcs_map_t)(M->copyJITResult());
+	return 0;
+}
+
+int perf_clang__hook_jitted_func(jitted_funcs_map_t map, void *ctx, bool is_err)
+{
+	std::unique_ptr<perf::PerfModule::HookMap>
+		hook_map((perf::PerfModule::HookMap *)map);
+
+	/* Do nothing but ensure map is deleted */
+	if (is_err)
+		return -1;
+
+	for (auto i : *hook_map) {
+		const char *hook_name = i.first.c_str();
+		perf_hook_func_t hook_func = i.second;
+
+		if (perf_hooks__set_hook(hook_name, hook_func, ctx))
+			return -1;
+	}
 	return 0;
 }
 }
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 23/30] perf clang jit: Collect the lowest address in maps section as map_base
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (21 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 22/30] perf clang jit: Actually JIT and hook in bpf loader Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26  7:03 ` [PATCH v3 24/30] perf clang jit: Retrive fd of BPF map from its offset Wang Nan
                   ` (6 subsequent siblings)
  29 siblings, 0 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

During jitting, find the lowest address in maps section and store its
value to _map_base. Pass its value out through perf_clang__compile_bpf().
map_base is useful for jitted functions accessing BPF maps.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/bpf-loader.c  | 39 +++++++++++++++++++++++++++++++++++++--
 tools/perf/util/c++/clang-c.h |  6 ++++--
 tools/perf/util/c++/clang.cpp | 15 +++++++++++++--
 tools/perf/util/c++/clang.h   |  5 +++++
 4 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index e50045f..81c6fed 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -47,6 +47,10 @@ struct bpf_prog_priv {
 	int *type_mapping;
 };
 
+struct bpf_obj_priv {
+	void *map_base;
+};
+
 static bool libbpf_initialized;
 
 struct bpf_object *
@@ -70,9 +74,20 @@ bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz, const char *name)
 	return obj;
 }
 
+static void
+clear_obj_priv(struct bpf_object *obj __maybe_unused,
+	       void *_priv)
+{
+	struct bpf_obj_priv *priv = _priv;
+
+	free(priv);
+}
+
 struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 {
 	struct bpf_object *obj;
+	void *map_base = NULL;
+	int err;
 
 	if (!libbpf_initialized) {
 		libbpf_set_print(libbpf_warning,
@@ -82,14 +97,14 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 	}
 
 	if (source) {
-		int err;
 		void *obj_buf;
 		size_t obj_buf_sz;
 		jitted_funcs_map_t jitted_funcs_map;
 
 		perf_clang__init();
 		err = perf_clang__compile_bpf(filename, &obj_buf,
-					      &obj_buf_sz, &jitted_funcs_map);
+					      &obj_buf_sz, &jitted_funcs_map,
+					      &map_base);
 		perf_clang__cleanup();
 		if (err) {
 			pr_warning("bpf: builtin compiling failed: %d, try external compiler\n", err);
@@ -119,7 +134,27 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 		return obj;
 	}
 
+	if (map_base) {
+		struct bpf_obj_priv *priv = calloc(sizeof(*priv), 1);
+
+		if (!priv) {
+			pr_debug("bpf: failed to alloc priv for object\n");
+			err = -ENOMEM;
+			goto errout;
+		}
+		priv->map_base = map_base;
+
+		err = bpf_object__set_priv(obj, priv, clear_obj_priv);
+		if (err) {
+			pr_debug("Failed to set priv for object '%s'\n", filename);
+			goto errout;
+		}
+	}
+
 	return obj;
+errout:
+	bpf_object__close(obj);
+	return ERR_PTR(err);
 }
 
 void bpf__clear(void)
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 021b1ad..4cf651b 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -22,7 +22,8 @@ extern void test__clang_callback(int x);
 extern int perf_clang__compile_bpf(const char *filename,
 				   void **p_obj_buf,
 				   size_t *p_obj_buf_sz,
-				   jitted_funcs_map_t *p_funcs_map);
+				   jitted_funcs_map_t *p_funcs_map,
+				   void **p_map_base);
 
 extern int
 perf_clang__hook_jitted_func(jitted_funcs_map_t map, void *ctx, bool is_err);
@@ -40,7 +41,8 @@ static inline int
 perf_clang__compile_bpf(const char *filename __maybe_unused,
 			void **p_obj_buf __maybe_unused,
 			size_t *p_obj_buf_sz __maybe_unused,
-			jitted_funcs_map_t *p_funcs_map __maybe_unused)
+			jitted_funcs_map_t *p_funcs_map __maybe_unused,
+			void **p_map_base __maybe_unused)
 {
 	return -ENOTSUP;
 }
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index f2608f5..f8ea9bd 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -122,7 +122,7 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
 	return getModuleFromSource(std::move(CFlags), Path, VFS);
 }
 
-PerfModule::PerfModule(std::unique_ptr<llvm::Module>&& M) : Module(std::move(M))
+PerfModule::PerfModule(std::unique_ptr<llvm::Module>&& M) : Module(std::move(M)), _map_base(NULL)
 {
 	for (llvm::Function& F : *Module) {
 		if (F.getLinkage() != llvm::GlobalValue::ExternalLinkage)
@@ -247,6 +247,13 @@ int PerfModule::doJIT(void)
 			&JITMemoryManager,
 			std::move(Resolver));
 
+	void *map_base = NULL;
+	for (llvm::GlobalValue *map : Maps) {
+		JITSymbol sym = CompileLayer.findSymbol(map->getName().str(), true);
+		void *address = (void *)(intptr_t)sym.getAddress();
+		if (!map_base || address < map_base)
+			map_base = address;
+	}
 
 	for (Function *F : JITFunctions) {
 		JITSymbol sym = CompileLayer.findSymbol(F->getName().str(), true);
@@ -266,6 +273,7 @@ int PerfModule::doJIT(void)
 				     << hook << ", only one is used\n";
 		JITResult[hook] = func;
 	}
+	_map_base = map_base;
 	return 0;
 }
 
@@ -389,7 +397,8 @@ void perf_clang__cleanup(void)
 int perf_clang__compile_bpf(const char *_filename,
 			    void **p_obj_buf,
 			    size_t *p_obj_buf_sz,
-			    jitted_funcs_map_t *p_funcs_map)
+			    jitted_funcs_map_t *p_funcs_map,
+			    void **p_map_base)
 {
 	using namespace perf;
 
@@ -422,6 +431,8 @@ int perf_clang__compile_bpf(const char *_filename,
 
 	if (p_funcs_map)
 		*p_funcs_map = (jitted_funcs_map_t)(M->copyJITResult());
+	if (p_map_base)
+		*p_map_base = M->getMapBase();
 	return 0;
 }
 
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index df2eb8f..aacedc2 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -26,6 +26,7 @@ class PerfModule {
 	std::set<llvm::Function *> JITFunctions;
 
 	HookMap JITResult;
+	void *_map_base;
 
 	void prepareBPF(void);
 	void prepareJIT(void);
@@ -38,6 +39,10 @@ class PerfModule {
 	{
 		return new HookMap(JITResult);
 	}
+	inline void *getMapBase(void)
+	{
+		return _map_base;
+	}
 
 	PerfModule(std::unique_ptr<llvm::Module>&& M);
 
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 24/30] perf clang jit: Retrive fd of BPF map from its offset
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (22 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 23/30] perf clang jit: Collect the lowest address in maps section as map_base Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26  7:03 ` [PATCH v3 25/30] perf clang jit: Allow jitted perf hook access BPF maps Wang Nan
                   ` (5 subsequent siblings)
  29 siblings, 0 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

bpf__map_fd() is introduced to retrive fd of a BPF map through its
offset in BPF object. This function is going be used in further
commits which allow scripts jitted by builtin clang access BPF maps.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/bpf-loader.c | 37 +++++++++++++++++++++++++++++++++++++
 tools/perf/util/bpf-loader.h | 19 +++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 81c6fed..86aa99b 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -19,6 +19,7 @@
 #include "parse-events.h"
 #include "llvm-utils.h"
 #include "c++/clang-c.h"
+#include "asm/bug.h"	// for WARN_ONCE
 
 #define DEFINE_PRINT_FN(name, level) \
 static int libbpf_##name(const char *fmt, ...)	\
@@ -1644,6 +1645,28 @@ int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
 	return 0;
 }
 
+int bpf__map_fd(struct bpf_object *obj, void *jit_map)
+{
+	struct bpf_obj_priv *priv = bpf_object__priv(obj);
+	struct bpf_map *map;
+	size_t map_offset;
+	void *map_base;
+
+	if (IS_ERR(priv))
+		return PTR_ERR(priv);
+	if (!priv)
+		return -EINVAL;
+
+	map_base = priv->map_base;
+	map_offset = jit_map - map_base;
+	map = bpf_object__find_map_by_offset(obj, map_offset);
+	WARN_ONCE(IS_ERR(map), "can't find map offset %zu from '%s'\n",
+		  map_offset, bpf_object__name(obj));
+	if (IS_ERR(map))
+		return -ENOENT;
+	return bpf_map__fd(map);
+}
+
 #define ERRNO_OFFSET(e)		((e) - __BPF_LOADER_ERRNO__START)
 #define ERRCODE_OFFSET(c)	ERRNO_OFFSET(BPF_LOADER_ERRNO__##c)
 #define NR_ERRNO	(__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START)
@@ -1825,3 +1848,17 @@ int bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused,
 	bpf__strerror_end(buf, size);
 	return 0;
 }
+
+int bpf__strerror_map_fd(struct bpf_object *obj, void *jit_map,
+			 int err, char *buf, size_t size)
+{
+	struct bpf_obj_priv *priv = bpf_object__priv(obj);
+	ptrdiff_t offset = priv ? jit_map - priv->map_base : jit_map - NULL;
+
+	bpf__strerror_head(err, buf, size);
+	bpf__strerror_entry(EINVAL, "No map in BPF object %s", bpf_object__name(obj));
+	bpf__strerror_entry(ENOENT, "Can't find map offset %lx in BPF object %s",
+			    (unsigned long)offset, bpf_object__name(obj));
+	bpf__strerror_end(buf, size);
+	return 0;
+}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index f2b737b..c40812b 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -84,6 +84,9 @@ int bpf__setup_stdout(struct perf_evlist *evlist);
 int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err,
 			       char *buf, size_t size);
 
+int bpf__map_fd(struct bpf_object *obj, void *jit_map);
+int bpf__strerror_map_fd(struct bpf_object *obj, void *jit_map,
+			 int err, char *buf, size_t size);
 #else
 static inline struct bpf_object *
 bpf__prepare_load(const char *filename __maybe_unused,
@@ -136,6 +139,13 @@ bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
 }
 
 static inline int
+bpf__map_fd(struct bpf_object *obj __maybe_unused,
+	    void *map_ptr __maybe_unused)
+{
+	return -ENOTSUP;
+}
+
+static inline int
 __bpf_strerror(char *buf, size_t size)
 {
 	if (!size)
@@ -196,5 +206,14 @@ bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused,
 {
 	return __bpf_strerror(buf, size);
 }
+
+static inline int
+bpf__strerror_map_fd(struct bpf_object *obj __maybe_unused,
+		     void *jit_map __maybe_unused,
+		     int err __maybe_unused,
+		     char *buf, size_t size);
+{
+	return __bpf_strerror(buf, size);
+}
 #endif
 #endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 25/30] perf clang jit: Allow jitted perf hook access BPF maps
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (23 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 24/30] perf clang jit: Retrive fd of BPF map from its offset Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26 17:09   ` Alexei Starovoitov
  2016-11-26  7:03 ` [PATCH v3 26/30] perf clang: Link BPF functions declaration into perf Wang Nan
                   ` (4 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Newly introduced jit-helpers.[ch] defines a series of helpers which helps
jitted perf hook functions accessing BPF maps defined in their BPF scripts.
The helpers fetches fd of 'struct bpf_map' from 'struct bpf_object' and the
address of 'struct bpf_map_def' in jitted file. 'struct bpf_object' is the
context passed to hooks.

Jit helpers added in this commits are all leading with 'perf_'. We don't use
'bpf_' prefix because in following commits 'bpf_' prefix is going to be assigned
to kernel side BPF map operations. Same operation has different protocol for
kernel and user.

 Example:

  $ cat ./test.c
  /*******************************************************/
  #define SEC(name) __attribute__((section(name), used))
  #define BPF_MAP_TYPE_ARRAY 2
  #define BPF_MAP_TYPE_PERF_EVENT_ARRAY 4
  #define BPF_FUNC_map_lookup_elem 1
  static void *(*bpf_map_lookup_elem)(void *map, void *key) =
      (void *) BPF_FUNC_map_lookup_elem;
  struct bpf_map_def {
      unsigned int type;
      unsigned int key_size;
      unsigned int value_size;
      unsigned int max_entries;
  };
  struct bpf_map_def SEC("maps") counter = {
      .type = BPF_MAP_TYPE_ARRAY,
      .key_size = sizeof(int),
      .value_size = sizeof(int),
      .max_entries = 1,
  };
  extern int perf_map_update_elem(void *ctx, struct bpf_map_def *map,
                         void *key, void *value, unsigned long flags);
  extern int perf_map_lookup_elem(void *ctx, struct bpf_map_def *map,
                         void *key, void *value);
  SEC("sys_close=SyS_close")
  int sys_close(void *ctx)
  {
      int key = 0;
      int *value;
      value = bpf_map_lookup_elem(&counter, &key);
      if (!value)
          return 0;
      __sync_fetch_and_add(value, 1);
      return 0;
  }
  extern int printf(const char *fmt, ...);
  SEC("perfhook:record_start")
  void record_start(void *ctx)
  {
      int key = 0;
      int value = 100000000;
      printf("Welcom to perf record\n");
      perf_map_update_elem(ctx, &counter, &key, &value, 0);
  }

  SEC("perfhook:record_end")
  void record_end(void *ctx)
  {
      int key = 0;
      int value;
      perf_map_lookup_elem(ctx, &counter, &key, &value);
      printf("Goodbye, perf record, value=%d\n", value);
  }
  char _license[] SEC("license") = "GPL";
  int _version SEC("version") = LINUX_VERSION_CODE;
  /*******************************************************/
  $ sudo perf record  -e ./test.c echo Hehe
  Welcom to perf record
  Hehe
  [ perf record: Woken up 1 times to write data ]
  Goodbye, perf record, value=100000644
  [ perf record: Captured and wrote 0.014 MB perf.data ]

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/Build         |  1 +
 tools/perf/util/c++/clang.cpp |  9 ++++++-
 tools/perf/util/jit-helpers.c | 57 +++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/jit-helpers.h | 28 +++++++++++++++++++++
 4 files changed, 94 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/util/jit-helpers.c
 create mode 100644 tools/perf/util/jit-helpers.h

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 743a889..33773cb 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -124,6 +124,7 @@ libperf-$(CONFIG_DWARF) += genelf_debug.o
 endif
 
 libperf-y += perf-hooks.o
+libperf-y += jit-helpers.o
 
 libperf-$(CONFIG_CXX) += c++/
 
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index f8ea9bd..48bd3ee 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -38,6 +38,7 @@
 #include "llvm-utils.h"
 #include "util-cxx.h"
 #include "perf-hooks.h"
+#include "jit-helpers.h"
 
 namespace perf {
 
@@ -196,12 +197,18 @@ PerfModule::toBPFObject(void)
 	return std::move(Buffer);
 }
 
+#define __stringify_1(x)	#x
+#define __stringify(x)		__stringify_1(x)
 static std::map<const std::string, const void *> exported_funcs =
 {
-#define EXPORT(f) {#f, (const void *)&f}
+#define EXPORT(f) {__stringify(f), (const void *)&f}
 	EXPORT(test__clang_callback),
 	EXPORT(printf),
 	EXPORT(puts),
+	EXPORT(JIT_HELPER_FUNC_NAME(map_update_elem)),
+	EXPORT(JIT_HELPER_FUNC_NAME(map_lookup_elem)),
+	EXPORT(JIT_HELPER_FUNC_NAME(map_get_next_key)),
+	EXPORT(JIT_HELPER_FUNC_NAME(map_pin)),
 #undef EXPORT
 };
 
diff --git a/tools/perf/util/jit-helpers.c b/tools/perf/util/jit-helpers.c
new file mode 100644
index 0000000..1a37a20
--- /dev/null
+++ b/tools/perf/util/jit-helpers.c
@@ -0,0 +1,57 @@
+/*
+ * jit-helper.c
+ *
+ * Copyright (C) 2016 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2016 Huawei Inc.
+ *
+ * Provide helpers which can be invoked by jit scripts attached to
+ * perf hooks.
+ */
+
+#include <util/jit-helpers.h>
+#include <util/bpf-loader.h>
+#include <bpf/libbpf.h>
+#include <bpf/bpf.h>
+
+#include "asm/bug.h"
+
+static int get_bpf_map_fd(struct bpf_object *obj, void *map)
+{
+	int fd;
+	char errbuf[BUFSIZ];
+
+	fd = bpf__map_fd(obj, map);
+	if (fd < 0) {
+		bpf__strerror_map_fd(obj, map, fd, errbuf, sizeof(errbuf));
+		WARN_ONCE(fd < 0, "Failed to get map fd: %s\n", errbuf);
+	}
+	return fd;
+}
+
+#define PARAMS(args...) args
+#define DEFINE_JIT_BPF_MAP_HELPER(name, proto, args)			\
+	JIT_BPF_MAP_HELPER(name, proto) {				\
+		int map_fd = get_bpf_map_fd(ctx, map);			\
+									\
+		if (map_fd < 0)						\
+			return map_fd;					\
+		return bpf_map_##name(map_fd, args);			\
+	}
+
+DEFINE_JIT_BPF_MAP_HELPER(update_elem,
+			  PARAMS(void *key, void *value, u64 flags),
+			  PARAMS(key, value, flags))
+
+DEFINE_JIT_BPF_MAP_HELPER(lookup_elem,
+			  PARAMS(void *key, void *value),
+			  PARAMS(key, value))
+
+DEFINE_JIT_BPF_MAP_HELPER(get_next_key,
+			  PARAMS(void *key, void *next_key),
+			  PARAMS(key, next_key))
+
+#define bpf_map_pin bpf_obj_pin
+DEFINE_JIT_BPF_MAP_HELPER(pin,
+			  PARAMS(const char *pathname),
+			  PARAMS(pathname));
+#undef bpf_map_pin
diff --git a/tools/perf/util/jit-helpers.h b/tools/perf/util/jit-helpers.h
new file mode 100644
index 0000000..b1f7479
--- /dev/null
+++ b/tools/perf/util/jit-helpers.h
@@ -0,0 +1,28 @@
+#ifndef JIT_HELPERS_H
+#define JIT_HELPERS_H
+
+#include <stdint.h>
+#include <util/perf-hooks.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define JIT_HELPER_FUNC_NAME(name) perf_##name
+
+#define JIT_HELPER(type, name, ...) \
+type JIT_HELPER_FUNC_NAME(name)(__VA_ARGS__)
+
+#define JIT_BPF_MAP_HELPER(name, ...) \
+	JIT_HELPER(int, map_##name, void *ctx, void *map, ##__VA_ARGS__)
+
+extern JIT_BPF_MAP_HELPER(update_elem, void *key, void *value, uint64_t flags);
+extern JIT_BPF_MAP_HELPER(lookup_elem, void *key, void *value);
+extern JIT_BPF_MAP_HELPER(get_next_key, void *key, void *next_key);
+extern JIT_BPF_MAP_HELPER(pin, const char *pathname);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 26/30] perf clang: Link BPF functions declaration into perf
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (24 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 25/30] perf clang jit: Allow jitted perf hook access BPF maps Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26 17:40   ` Alexei Starovoitov
  2016-11-26  7:03 ` [PATCH v3 27/30] perf clang: Declare BPF functions for BPF scripts automatically Wang Nan
                   ` (3 subsequent siblings)
  29 siblings, 1 reply; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Use a shell script to generate BPF functions declarations from kernel
source code, embed the generated header into a C string. Following
commits will utilizes clang's virtual file system to automatically
include this header to all BPF scripts.

The generated header is wrapped by a BUILTIN_CLANG_NO_DEFAULT_INCLUDE.
This macro will be used by following commits to allow user disable this
and other builtin includes.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/c++/Build                |   1 +
 tools/perf/util/c++/bpf-funcs-str.c      | 228 +++++++++++++++++++++++++++++++
 tools/perf/util/c++/clang-bpf-includes.h |  12 ++
 3 files changed, 241 insertions(+)
 create mode 100644 tools/perf/util/c++/bpf-funcs-str.c
 create mode 100644 tools/perf/util/c++/clang-bpf-includes.h

diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
index 988fef1..bd71abf 100644
--- a/tools/perf/util/c++/Build
+++ b/tools/perf/util/c++/Build
@@ -1,2 +1,3 @@
 libperf-$(CONFIG_CLANGLLVM) += clang.o
 libperf-$(CONFIG_CLANGLLVM) += clang-test.o
+libperf-$(CONFIG_CLANGLLVM) += bpf-funcs-str.o
diff --git a/tools/perf/util/c++/bpf-funcs-str.c b/tools/perf/util/c++/bpf-funcs-str.c
new file mode 100644
index 0000000..f6bcf76
--- /dev/null
+++ b/tools/perf/util/c++/bpf-funcs-str.c
@@ -0,0 +1,228 @@
+/*
+ * This file is generated by following script:
+ *
+ * #!/bin/bash
+ * TEMP_KBUILD=$(mktemp -d)
+ * KERNEL_DIR=$(pwd)
+ * OUTPUT=tools/perf/util/c++/bpf-funcs-str.c
+ * rm -rf $OUTPUT
+ * echo "Use temp dir: $TEMP_KBUILD"
+ * function finish()
+ * {
+ * 	rm -rf $TEMP_KBUILD
+ * }
+ * trap finish EXIT
+ * SRCLIST=$(find -name "*.c" | xargs grep bpf_func_proto -l)
+ * cd $TEMP_KBUILD
+ * yes '' | make -C $KERNEL_DIR O=`pwd` oldconfig
+ * cat << EOF >> ./.config
+ * CONFIG_BPF=y
+ * CONFIG_BPF_SYSCALL=y
+ * CONFIG_PERF_EVENTS=y
+ * CONFIG_SOCK_CGROUP_DATA=y
+ * EOF
+ * yes '' | make -C $KERNEL_DIR O=`pwd` oldconfig
+ * FIXOBJLIST=""
+ * for src in ${SRCLIST}
+ * do
+ * 	mkdir -p $(dirname $src)
+ * 	cat << EOF > "${src}-fix.c"
+ * #include <linux/init.h>
+ * #undef __init
+ * #define __init __attribute__((constructor))
+ * #include "`basename $src`"
+ * EOF
+ * 	if [ $(basename $src) == "syscall.c" ]
+ * 	then
+ * 		cat << EOF >> "${src}-fix.c"
+ * const struct bpf_verifier_ops *
+ * find_prog_type_export(enum bpf_prog_type type)
+ * {
+ * 	struct bpf_prog_aux aux;
+ * 	struct bpf_prog p = {.aux = &aux };
+ * 	if (find_prog_type(type, &p))
+ * 		return NULL;
+ * 	return p.aux->ops;
+ * }
+ * EOF
+ * 	fi
+ * 	FIXOBJLIST="$FIXOBJLIST ${src}-fix.o"
+ * done
+ * function dolink()
+ * {
+ * 	touch ./syms.c
+ * 	echo gcc kernel/bpf/main.o ./syms.c $FIXOBJLIST -o ./gen
+ * 	gcc kernel/bpf/main.o ./syms.c $FIXOBJLIST -o ./gen
+ * }
+ * MAIN=kernel/bpf/main.c
+ * cat << EOF > $MAIN
+ * #include <uapi/linux/bpf.h>
+ * #include <linux/bpf.h>
+ * struct bpf_func {
+ *   const char *name;
+ *   int id;
+ * } bpf_funcs[] = {
+ * EOF
+ * grep '^[[:space:]]BPF_FUNC_[^ ]*,' $KERNEL_DIR/include/uapi/linux/bpf.h | \
+ * 	sed -e 's/.*BPF_FUNC_\([^,]*\),.*$/\1/g' | \
+ * 	xargs -n 1 sh -c 'echo {.name = \"$1\", .id = BPF_FUNC_$1}, >> '"$MAIN" sh
+ * cat << EOF >> $MAIN
+ * {NULL, -1},
+ * };
+ * int capable(int x) {return 1;}
+ * int trace_printk_init_buffers(void) {return 0;}
+ * static int x;
+ * void *metadata_dst_alloc_percpu(int a, int b) {return &x;}
+ * int ___ratelimit(void *a, const void *func) {return 0;}
+ * extern const struct bpf_verifier_ops *
+ * find_prog_type_export(enum bpf_prog_type type);
+ * extern int printf(const char *fmt, ...);
+ * int main(int argc, char *argv[])
+ * {
+ * 	struct bpf_func *f = &bpf_funcs[0];
+ * 	printf("#ifndef BPF_FUNCS_DEFINED\n");
+ * 	printf("#define BPF_FUNCS_DEFINED\n");
+ * 	while (f->id != -1) {
+ * 		enum bpf_prog_type t;
+ * 		const enum bpf_arg_type *argt;
+ * 		const struct bpf_verifier_ops *ops = NULL;
+ * 		const struct bpf_func_proto *proto = NULL;
+ * 		if (f->id == 0)
+ * 			goto skip;
+ * 		for (t = BPF_PROG_TYPE_UNSPEC + 1; ; t++) {
+ * 			ops = find_prog_type_export(t);
+ * 			if (!ops)
+ * 				break;
+ * 			proto = ops->get_func_proto(f->id);
+ * 			if (proto)
+ * 				break;
+ * 		}
+ * 		if (!proto) {
+ * 			printf("static void (*%s)(void) = (void *)-1;\n", f->name);
+ * 			continue;
+ * 		}
+ * 		printf("static ");
+ * 		switch (proto->ret_type) {
+ * 		case RET_INTEGER:
+ * 			printf("long ");
+ * 			break;
+ * 		case RET_PTR_TO_MAP_VALUE_OR_NULL:
+ * 			printf("void *");
+ * 			break;
+ * 		default:
+ * 		case RET_VOID:
+ * 			printf("void ");
+ * 			break;
+ * 		}
+ * 		printf("(*bpf_%s)(", f->name);
+ * 		for (argt = &proto->arg1_type; argt <= &proto->arg5_type; argt++) {
+ * 			if (*argt == ARG_DONTCARE) {
+ * 				if (argt == &proto->arg1_type)
+ * 					printf("void");
+ * 				else if (strcmp(f->name, "trace_printk") == 0) {
+ * 					printf(", ...");
+ * 					goto finish;
+ * 				}
+ * 				goto finish;
+ * 			}
+ * 			if (argt != &proto->arg1_type)
+ * 				printf(", ");
+ * 			switch (*argt) {
+ * 			case ARG_CONST_MAP_PTR:
+ * 			case ARG_PTR_TO_MAP_KEY:
+ * 			case ARG_PTR_TO_MAP_VALUE:
+ * 			case ARG_PTR_TO_STACK:
+ * 			case ARG_PTR_TO_RAW_STACK:
+ * 			case ARG_PTR_TO_CTX:
+ * 				printf("void *");
+ * 				break;
+ * 			default:
+ * 				printf("unsigned long");
+ * 				break;
+ * 			}
+ * 		}
+ * finish:
+ * 		printf(") = (void *)%d;\n", f->id);
+ * skip:
+ * 		f++;
+ * 	}
+ * 	printf("#endif\n");
+ * 	return 0;
+ * }
+ * EOF
+ * make -j8 KBUILD_CFLAGS_KERNEL=-mpreferred-stack-boundary=4 kernel/bpf/main.o $FIXOBJLIST
+ * rm -f ./syms.c
+ * export LANG=POSIX
+ * export LC_ALL=POSIX
+ * dolink 2>&1 | \
+ *        grep 'undefined reference' | \
+ *        awk -F "\`" '{print $2}' | \
+ *        sed "s/'$//g" | sort | uniq | \
+ *        xargs -n 1 sh -c 'echo "int $1 __attribute__((weak));" >> ./syms.c' sh
+ * dolink
+ * cd $KERNEL_DIR
+ * unset X
+ * cat << EOF > $OUTPUT
+ * /$X*
+ *  * This file is generated by following script:
+ *  *
+ * EOF
+ * cat $0 | awk '$0 != "" {print " * " $0}' >> $OUTPUT
+ * echo ' *''/' >> $OUTPUT
+ * echo '#include "clang-bpf-includes.h"' >> $OUTPUT
+ * echo 'const char clang_builtin_bpf_funcs_str[] =' >> $OUTPUT
+ * echo '"#ifdef BUILTIN_CLANG_DEFAULT_INCLUDE\n"' >> $OUTPUT
+ * $TEMP_KBUILD/gen | awk '{print "\""$0"\\n\""}' >> $OUTPUT
+ * echo '"#endif\n"' >> $OUTPUT
+ * echo ';' >> $OUTPUT
+ * echo "Finish generating " $OUTPUT
+ */
+#include "clang-bpf-includes.h"
+const char clang_builtin_bpf_funcs_str[] =
+"#ifdef BUILTIN_CLANG_DEFAULT_INCLUDE\n"
+"#ifndef BPF_FUNCS_DEFINED\n"
+"#define BPF_FUNCS_DEFINED\n"
+"static void *(*bpf_map_lookup_elem)(void *, void *) = (void *)1;\n"
+"static long (*bpf_map_update_elem)(void *, void *, void *, unsigned long) = (void *)2;\n"
+"static long (*bpf_map_delete_elem)(void *, void *) = (void *)3;\n"
+"static long (*bpf_probe_read)(void *, unsigned long, unsigned long) = (void *)4;\n"
+"static long (*bpf_ktime_get_ns)(void) = (void *)5;\n"
+"static long (*bpf_trace_printk)(void *, unsigned long, ...) = (void *)6;\n"
+"static long (*bpf_get_prandom_u32)(void) = (void *)7;\n"
+"static long (*bpf_get_smp_processor_id)(void) = (void *)8;\n"
+"static long (*bpf_skb_store_bytes)(void *, unsigned long, void *, unsigned long, unsigned long) = (void *)9;\n"
+"static long (*bpf_l3_csum_replace)(void *, unsigned long, unsigned long, unsigned long, unsigned long) = (void *)10;\n"
+"static long (*bpf_l4_csum_replace)(void *, unsigned long, unsigned long, unsigned long, unsigned long) = (void *)11;\n"
+"static void (*bpf_tail_call)(void *, void *, unsigned long) = (void *)12;\n"
+"static long (*bpf_clone_redirect)(void *, unsigned long, unsigned long) = (void *)13;\n"
+"static long (*bpf_get_current_pid_tgid)(void) = (void *)14;\n"
+"static long (*bpf_get_current_uid_gid)(void) = (void *)15;\n"
+"static long (*bpf_get_current_comm)(void *, unsigned long) = (void *)16;\n"
+"static long (*bpf_get_cgroup_classid)(void *) = (void *)17;\n"
+"static long (*bpf_skb_vlan_push)(void *, unsigned long, unsigned long) = (void *)18;\n"
+"static long (*bpf_skb_vlan_pop)(void *) = (void *)19;\n"
+"static long (*bpf_skb_get_tunnel_key)(void *, void *, unsigned long, unsigned long) = (void *)20;\n"
+"static long (*bpf_skb_set_tunnel_key)(void *, void *, unsigned long, unsigned long) = (void *)21;\n"
+"static long (*bpf_perf_event_read)(void *, unsigned long) = (void *)22;\n"
+"static long (*bpf_redirect)(unsigned long, unsigned long) = (void *)23;\n"
+"static long (*bpf_get_route_realm)(void *) = (void *)24;\n"
+"static long (*bpf_perf_event_output)(void *, void *, unsigned long, void *, unsigned long) = (void *)25;\n"
+"static long (*bpf_skb_load_bytes)(void *, unsigned long, void *, unsigned long) = (void *)26;\n"
+"static long (*bpf_get_stackid)(void *, void *, unsigned long) = (void *)27;\n"
+"static long (*bpf_csum_diff)(void *, unsigned long, void *, unsigned long, unsigned long) = (void *)28;\n"
+"static long (*bpf_skb_get_tunnel_opt)(void *, void *, unsigned long) = (void *)29;\n"
+"static long (*bpf_skb_set_tunnel_opt)(void *, void *, unsigned long) = (void *)30;\n"
+"static long (*bpf_skb_change_proto)(void *, unsigned long, unsigned long) = (void *)31;\n"
+"static long (*bpf_skb_change_type)(void *, unsigned long) = (void *)32;\n"
+"static long (*bpf_skb_under_cgroup)(void *, void *, unsigned long) = (void *)33;\n"
+"static long (*bpf_get_hash_recalc)(void *) = (void *)34;\n"
+"static long (*bpf_get_current_task)(void) = (void *)35;\n"
+"static long (*bpf_probe_write_user)(unsigned long, void *, unsigned long) = (void *)36;\n"
+"static long (*bpf_current_task_under_cgroup)(void *, unsigned long) = (void *)37;\n"
+"static long (*bpf_skb_change_tail)(void *, unsigned long, unsigned long) = (void *)38;\n"
+"static long (*bpf_skb_pull_data)(void *, unsigned long) = (void *)39;\n"
+"static long (*bpf_csum_update)(void *, unsigned long) = (void *)40;\n"
+"static long (*bpf_set_hash_invalid)(void *) = (void *)41;\n"
+"#endif\n"
+"#endif\n"
+;
diff --git a/tools/perf/util/c++/clang-bpf-includes.h b/tools/perf/util/c++/clang-bpf-includes.h
new file mode 100644
index 0000000..385a5bb
--- /dev/null
+++ b/tools/perf/util/c++/clang-bpf-includes.h
@@ -0,0 +1,12 @@
+#ifndef CLANG_BPF_INCLUDS_H
+#define CLANG_BPF_INCLUDS_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char clang_builtin_bpf_funcs_str[];
+
+#ifdef __cplusplus
+}
+#endif
+#endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 27/30] perf clang: Declare BPF functions for BPF scripts automatically
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (25 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 26/30] perf clang: Link BPF functions declaration into perf Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26  7:03 ` [PATCH v3 28/30] perf clang: Include helpers to BPF scripts Wang Nan
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Use Clang's OverlayFileSystem, add '-include' options to make builtin
clang define BPF functions. After this patch BPF script writer needn't
define BPF functions by their own.

Add -DBUILTIN_CLANG_DEFAULT_INCLUDE to builtin clang so when adopting
builtin clang BPF functions can be automatically defined, and keep
undefined when using external clang. Passing a
-UBUILTIN_CLANG_DEFAULT_INCLUDE to cancel this defaudefinition.

Test cases are updated to avoid redefinition of these functions.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/tests/bpf-script-example.c         | 18 +++++++++------
 tools/perf/tests/bpf-script-test-prologue.c   |  2 ++
 tools/perf/tests/bpf-script-test-relocation.c | 18 +++++++++------
 tools/perf/util/c++/clang.cpp                 | 33 ++++++++++++++++++++++++++-
 4 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
index ccbc19c..42dc341 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -8,13 +8,6 @@
 #endif
 #define BPF_ANY 0
 #define BPF_MAP_TYPE_ARRAY 2
-#define BPF_FUNC_map_lookup_elem 1
-#define BPF_FUNC_map_update_elem 2
-
-static void *(*bpf_map_lookup_elem)(void *map, void *key) =
-	(void *) BPF_FUNC_map_lookup_elem;
-static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
-	(void *) BPF_FUNC_map_update_elem;
 
 struct bpf_map_def {
 	unsigned int type;
@@ -24,6 +17,17 @@ struct bpf_map_def {
 };
 
 #define SEC(NAME) __attribute__((section(NAME), used))
+
+#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
+#define BPF_FUNC_map_lookup_elem 1
+#define BPF_FUNC_map_update_elem 2
+
+static void *(*bpf_map_lookup_elem)(void *map, void *key) =
+	(void *) BPF_FUNC_map_lookup_elem;
+static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
+	(void *) BPF_FUNC_map_update_elem;
+#endif
+
 struct bpf_map_def SEC("maps") flip_table = {
 	.type = BPF_MAP_TYPE_ARRAY,
 	.key_size = sizeof(int),
diff --git a/tools/perf/tests/bpf-script-test-prologue.c b/tools/perf/tests/bpf-script-test-prologue.c
index 7230e62..ada812b 100644
--- a/tools/perf/tests/bpf-script-test-prologue.c
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -13,8 +13,10 @@
 #define FMODE_READ		0x1
 #define FMODE_WRITE		0x2
 
+#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
 static void (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
 	(void *) 6;
+#endif
 
 SEC("func=null_lseek file->f_mode offset orig")
 int bpf_func__null_lseek(void *ctx, int err, unsigned long f_mode,
diff --git a/tools/perf/tests/bpf-script-test-relocation.c b/tools/perf/tests/bpf-script-test-relocation.c
index 93af774..57c96a3 100644
--- a/tools/perf/tests/bpf-script-test-relocation.c
+++ b/tools/perf/tests/bpf-script-test-relocation.c
@@ -8,13 +8,6 @@
 #endif
 #define BPF_ANY 0
 #define BPF_MAP_TYPE_ARRAY 2
-#define BPF_FUNC_map_lookup_elem 1
-#define BPF_FUNC_map_update_elem 2
-
-static void *(*bpf_map_lookup_elem)(void *map, void *key) =
-	(void *) BPF_FUNC_map_lookup_elem;
-static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
-	(void *) BPF_FUNC_map_update_elem;
 
 struct bpf_map_def {
 	unsigned int type;
@@ -24,6 +17,17 @@ struct bpf_map_def {
 };
 
 #define SEC(NAME) __attribute__((section(NAME), used))
+
+#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
+#define BPF_FUNC_map_lookup_elem 1
+#define BPF_FUNC_map_update_elem 2
+
+static void *(*bpf_map_lookup_elem)(void *map, void *key) =
+	(void *) BPF_FUNC_map_lookup_elem;
+static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
+	(void *) BPF_FUNC_map_update_elem;
+#endif
+
 struct bpf_map_def SEC("maps") my_table = {
 	.type = BPF_MAP_TYPE_ARRAY,
 	.key_size = sizeof(int),
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 48bd3ee..926dae1 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -39,9 +39,17 @@
 #include "util-cxx.h"
 #include "perf-hooks.h"
 #include "jit-helpers.h"
+#include "clang-bpf-includes.h"
 
 namespace perf {
 
+static struct BPFHeader {
+	llvm::StringRef Path;
+	llvm::StringRef Content;
+} BPFHeaders[] = {
+	{"/virtual/bpf-funcs.h", clang_builtin_bpf_funcs_str},
+};
+
 static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
 
 using namespace clang;
@@ -66,6 +74,11 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
 		"-x", "c"};
 
 	CCArgs.append(CFlags.begin(), CFlags.end());
+	for (BPFHeader &h : BPFHeaders) {
+		CCArgs.append(1, "-include");
+		CCArgs.append(1, h.Path.begin());
+	}
+
 	CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);
 
 	FrontendOptions& Opts = CI->getFrontendOpts();
@@ -74,6 +87,22 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
 	return CI;
 }
 
+static IntrusiveRefCntPtr<vfs::FileSystem>
+addBPFHeaders(IntrusiveRefCntPtr<vfs::FileSystem> VFS)
+{
+	using namespace vfs;
+
+	llvm::IntrusiveRefCntPtr<OverlayFileSystem> OverlayFS(
+			new OverlayFileSystem(VFS));
+	llvm::IntrusiveRefCntPtr<InMemoryFileSystem> MemFS(
+			new InMemoryFileSystem(true));
+	OverlayFS->pushOverlay(MemFS);
+
+	for (BPFHeader &h : BPFHeaders)
+		MemFS->addFile(h.Path, 0, llvm::MemoryBuffer::getMemBuffer(h.Content));
+	return OverlayFS;
+}
+
 static std::unique_ptr<PerfModule>
 getModuleFromSource(llvm::opt::ArgStringList CFlags,
 		    StringRef Path, IntrusiveRefCntPtr<vfs::FileSystem> VFS)
@@ -81,7 +110,8 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags,
 	CompilerInstance Clang;
 	Clang.createDiagnostics();
 
-	Clang.setVirtualFileSystem(&*VFS);
+	IntrusiveRefCntPtr<vfs::FileSystem> OverlayVFS = addBPFHeaders(VFS);
+	Clang.setVirtualFileSystem(&*OverlayVFS);
 
 	IntrusiveRefCntPtr<CompilerInvocation> CI =
 		createCompilerInvocation(std::move(CFlags), Path,
@@ -363,6 +393,7 @@ public:
 	{
 		CFlags.push_back(KVerDef.c_str());
 		CFlags.push_back(NRCpusDef.c_str());
+		CFlags.push_back("-DBUILTIN_CLANG_DEFAULT_INCLUDE");
 
 		fillCFlagsFromString(CFlags, clang_opt);
 		fillCFlagsFromString(CFlags, kbuild_include_opts, true);
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 28/30] perf clang: Include helpers to BPF scripts
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (26 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 27/30] perf clang: Declare BPF functions for BPF scripts automatically Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26  7:03 ` [PATCH v3 29/30] perf clang builtin: Define hook helpers by default Wang Nan
  2016-11-26  7:03 ` [PATCH v3 30/30] perf clang jit: Export getpid() to perf hook Wang Nan
  29 siblings, 0 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Automatically include some commonly used macros and struct definitions
into BPF scripts. Script writers are no longer required to define
'SEC' and 'struct bpf_map_def' in each of their scripts.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/tests/bpf-script-example.c         |  2 +-
 tools/perf/tests/bpf-script-test-kbuild.c     |  2 ++
 tools/perf/tests/bpf-script-test-prologue.c   |  4 +++-
 tools/perf/tests/bpf-script-test-relocation.c |  3 +--
 tools/perf/util/c++/Build                     |  1 +
 tools/perf/util/c++/bpf-helper-str.c          | 15 +++++++++++++++
 tools/perf/util/c++/clang-bpf-includes.h      |  1 +
 tools/perf/util/c++/clang.cpp                 |  1 +
 8 files changed, 25 insertions(+), 4 deletions(-)
 create mode 100644 tools/perf/util/c++/bpf-helper-str.c

diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
index 42dc341..e60bebf 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -9,6 +9,7 @@
 #define BPF_ANY 0
 #define BPF_MAP_TYPE_ARRAY 2
 
+#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
 struct bpf_map_def {
 	unsigned int type;
 	unsigned int key_size;
@@ -18,7 +19,6 @@ struct bpf_map_def {
 
 #define SEC(NAME) __attribute__((section(NAME), used))
 
-#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
 #define BPF_FUNC_map_lookup_elem 1
 #define BPF_FUNC_map_update_elem 2
 
diff --git a/tools/perf/tests/bpf-script-test-kbuild.c b/tools/perf/tests/bpf-script-test-kbuild.c
index 3626924..f1b48a4 100644
--- a/tools/perf/tests/bpf-script-test-kbuild.c
+++ b/tools/perf/tests/bpf-script-test-kbuild.c
@@ -6,7 +6,9 @@
 # error Need LINUX_VERSION_CODE
 # error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
 #endif
+#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
 #define SEC(NAME) __attribute__((section(NAME), used))
+#endif
 
 #include <uapi/linux/fs.h>
 #include <uapi/asm/ptrace.h>
diff --git a/tools/perf/tests/bpf-script-test-prologue.c b/tools/perf/tests/bpf-script-test-prologue.c
index ada812b..e2176c9 100644
--- a/tools/perf/tests/bpf-script-test-prologue.c
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -6,7 +6,6 @@
 # error Need LINUX_VERSION_CODE
 # error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
 #endif
-#define SEC(NAME) __attribute__((section(NAME), used))
 
 #include <uapi/linux/fs.h>
 
@@ -14,6 +13,9 @@
 #define FMODE_WRITE		0x2
 
 #ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
+
+#define SEC(NAME) __attribute__((section(NAME), used))
+
 static void (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
 	(void *) 6;
 #endif
diff --git a/tools/perf/tests/bpf-script-test-relocation.c b/tools/perf/tests/bpf-script-test-relocation.c
index 57c96a3..bb54926 100644
--- a/tools/perf/tests/bpf-script-test-relocation.c
+++ b/tools/perf/tests/bpf-script-test-relocation.c
@@ -9,6 +9,7 @@
 #define BPF_ANY 0
 #define BPF_MAP_TYPE_ARRAY 2
 
+#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
 struct bpf_map_def {
 	unsigned int type;
 	unsigned int key_size;
@@ -17,8 +18,6 @@ struct bpf_map_def {
 };
 
 #define SEC(NAME) __attribute__((section(NAME), used))
-
-#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
 #define BPF_FUNC_map_lookup_elem 1
 #define BPF_FUNC_map_update_elem 2
 
diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
index bd71abf..faa0268 100644
--- a/tools/perf/util/c++/Build
+++ b/tools/perf/util/c++/Build
@@ -1,3 +1,4 @@
 libperf-$(CONFIG_CLANGLLVM) += clang.o
 libperf-$(CONFIG_CLANGLLVM) += clang-test.o
 libperf-$(CONFIG_CLANGLLVM) += bpf-funcs-str.o
+libperf-$(CONFIG_CLANGLLVM) += bpf-helper-str.o
diff --git a/tools/perf/util/c++/bpf-helper-str.c b/tools/perf/util/c++/bpf-helper-str.c
new file mode 100644
index 0000000..17f915c
--- /dev/null
+++ b/tools/perf/util/c++/bpf-helper-str.c
@@ -0,0 +1,15 @@
+#include "clang-bpf-includes.h"
+const char clang_builtin_bpf_helper_str[] =
+"#ifdef BUILTIN_CLANG_DEFAULT_INCLUDE\n"
+"#ifndef BPF_HELPER_DEFINED\n"
+"#define BPF_HELPER_DEFINED\n"
+"struct bpf_map_def {\n"
+"	unsigned int type;\n"
+"	unsigned int key_size;\n"
+"	unsigned int value_size;\n"
+"	unsigned int max_entries;\n"
+"};\n"
+"#define SEC(NAME) __attribute__((section(NAME), used))\n"
+"#endif\n"
+"#endif"
+;
diff --git a/tools/perf/util/c++/clang-bpf-includes.h b/tools/perf/util/c++/clang-bpf-includes.h
index 385a5bb..577b40c 100644
--- a/tools/perf/util/c++/clang-bpf-includes.h
+++ b/tools/perf/util/c++/clang-bpf-includes.h
@@ -5,6 +5,7 @@ extern "C" {
 #endif
 
 extern const char clang_builtin_bpf_funcs_str[];
+extern const char clang_builtin_bpf_helper_str[];
 
 #ifdef __cplusplus
 }
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 926dae1..5c1efe8 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -48,6 +48,7 @@ static struct BPFHeader {
 	llvm::StringRef Content;
 } BPFHeaders[] = {
 	{"/virtual/bpf-funcs.h", clang_builtin_bpf_funcs_str},
+	{"/virtual/bpf-helper.h", clang_builtin_bpf_helper_str},
 };
 
 static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 29/30] perf clang builtin: Define hook helpers by default
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (27 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 28/30] perf clang: Include helpers to BPF scripts Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  2016-11-26  7:03 ` [PATCH v3 30/30] perf clang jit: Export getpid() to perf hook Wang Nan
  29 siblings, 0 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

Append declarations of helpers to default include file. All functions
appear in exported_funcs array should be declared here except
test__clang_callback, because it is used for perf test only.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/c++/bpf-helper-str.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/tools/perf/util/c++/bpf-helper-str.c b/tools/perf/util/c++/bpf-helper-str.c
index 17f915c..f4d6d57 100644
--- a/tools/perf/util/c++/bpf-helper-str.c
+++ b/tools/perf/util/c++/bpf-helper-str.c
@@ -10,6 +10,13 @@ const char clang_builtin_bpf_helper_str[] =
 "	unsigned int max_entries;\n"
 "};\n"
 "#define SEC(NAME) __attribute__((section(NAME), used))\n"
+"extern int printf(const char *, ...);\n"
+"extern int puts(const char *);\n"
+"extern int perf_map_update_elem(void *, void *, void *, void *, unsigned long);\n"
+"extern int perf_map_lookup_elem(void *, void *, void *, void *);\n"
+"extern int perf_map_get_next_key(void *, void *, void *, void *);\n"
+"extern int perf_map_pin(void *, void *, const char *);\n"
+"extern int perf_map_get(const char *);\n"
 "#endif\n"
 "#endif"
 ;
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [PATCH v3 30/30] perf clang jit: Export getpid() to perf hook
  2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
                   ` (28 preceding siblings ...)
  2016-11-26  7:03 ` [PATCH v3 29/30] perf clang builtin: Define hook helpers by default Wang Nan
@ 2016-11-26  7:03 ` Wang Nan
  29 siblings, 0 replies; 73+ messages in thread
From: Wang Nan @ 2016-11-26  7:03 UTC (permalink / raw)
  To: acme, ast
  Cc: lizefan, hekuang, linux-kernel, pi3orama, joe, Wang Nan, Jiri Olsa

After this patch perf hooks can retrive pid of perf itself by calling
getpid. It is important for excluding event from perf.

This commit is also an example to show how to export more helpers to
hooked script.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/c++/bpf-helper-str.c | 1 +
 tools/perf/util/c++/clang.cpp        | 1 +
 2 files changed, 2 insertions(+)

diff --git a/tools/perf/util/c++/bpf-helper-str.c b/tools/perf/util/c++/bpf-helper-str.c
index f4d6d57..1ad6ec0 100644
--- a/tools/perf/util/c++/bpf-helper-str.c
+++ b/tools/perf/util/c++/bpf-helper-str.c
@@ -12,6 +12,7 @@ const char clang_builtin_bpf_helper_str[] =
 "#define SEC(NAME) __attribute__((section(NAME), used))\n"
 "extern int printf(const char *, ...);\n"
 "extern int puts(const char *);\n"
+"extern int getpid(void);\n"
 "extern int perf_map_update_elem(void *, void *, void *, void *, unsigned long);\n"
 "extern int perf_map_lookup_elem(void *, void *, void *, void *);\n"
 "extern int perf_map_get_next_key(void *, void *, void *, void *);\n"
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 5c1efe8..213c58f 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -236,6 +236,7 @@ static std::map<const std::string, const void *> exported_funcs =
 	EXPORT(test__clang_callback),
 	EXPORT(printf),
 	EXPORT(puts),
+	EXPORT(getpid),
 	EXPORT(JIT_HELPER_FUNC_NAME(map_update_elem)),
 	EXPORT(JIT_HELPER_FUNC_NAME(map_lookup_elem)),
 	EXPORT(JIT_HELPER_FUNC_NAME(map_get_next_key)),
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 25/30] perf clang jit: Allow jitted perf hook access BPF maps
  2016-11-26  7:03 ` [PATCH v3 25/30] perf clang jit: Allow jitted perf hook access BPF maps Wang Nan
@ 2016-11-26 17:09   ` Alexei Starovoitov
  0 siblings, 0 replies; 73+ messages in thread
From: Alexei Starovoitov @ 2016-11-26 17:09 UTC (permalink / raw)
  To: Wang Nan
  Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe, Jiri Olsa

On Sat, Nov 26, 2016 at 07:03:49AM +0000, Wang Nan wrote:
> Newly introduced jit-helpers.[ch] defines a series of helpers which helps
> jitted perf hook functions accessing BPF maps defined in their BPF scripts.
> The helpers fetches fd of 'struct bpf_map' from 'struct bpf_object' and the
> address of 'struct bpf_map_def' in jitted file. 'struct bpf_object' is the
> context passed to hooks.
> 
> Jit helpers added in this commits are all leading with 'perf_'. We don't use
> 'bpf_' prefix because in following commits 'bpf_' prefix is going to be assigned
> to kernel side BPF map operations. Same operation has different protocol for
> kernel and user.
> 
>  Example:
> 
>   $ cat ./test.c
>   /*******************************************************/
>   #define SEC(name) __attribute__((section(name), used))
>   #define BPF_MAP_TYPE_ARRAY 2
>   #define BPF_MAP_TYPE_PERF_EVENT_ARRAY 4
>   #define BPF_FUNC_map_lookup_elem 1
>   static void *(*bpf_map_lookup_elem)(void *map, void *key) =
>       (void *) BPF_FUNC_map_lookup_elem;
>   struct bpf_map_def {
>       unsigned int type;
>       unsigned int key_size;
>       unsigned int value_size;
>       unsigned int max_entries;
>   };
>   struct bpf_map_def SEC("maps") counter = {
>       .type = BPF_MAP_TYPE_ARRAY,
>       .key_size = sizeof(int),
>       .value_size = sizeof(int),
>       .max_entries = 1,
>   };
>   extern int perf_map_update_elem(void *ctx, struct bpf_map_def *map,
>                          void *key, void *value, unsigned long flags);
>   extern int perf_map_lookup_elem(void *ctx, struct bpf_map_def *map,
>                          void *key, void *value);
>   SEC("sys_close=SyS_close")
>   int sys_close(void *ctx)
>   {
>       int key = 0;
>       int *value;
>       value = bpf_map_lookup_elem(&counter, &key);
>       if (!value)
>           return 0;
>       __sync_fetch_and_add(value, 1);
>       return 0;
>   }
>   extern int printf(const char *fmt, ...);
>   SEC("perfhook:record_start")
>   void record_start(void *ctx)
>   {
>       int key = 0;
>       int value = 100000000;
>       printf("Welcom to perf record\n");
>       perf_map_update_elem(ctx, &counter, &key, &value, 0);
>   }
> 
>   SEC("perfhook:record_end")
>   void record_end(void *ctx)
>   {
>       int key = 0;
>       int value;
>       perf_map_lookup_elem(ctx, &counter, &key, &value);
>       printf("Goodbye, perf record, value=%d\n", value);
>   }
>   char _license[] SEC("license") = "GPL";
>   int _version SEC("version") = LINUX_VERSION_CODE;
>   /*******************************************************/
>   $ sudo perf record  -e ./test.c echo Hehe
>   Welcom to perf record
>   Hehe
>   [ perf record: Woken up 1 times to write data ]
>   Goodbye, perf record, value=100000644
>   [ perf record: Captured and wrote 0.014 MB perf.data ]
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
...
> +#define __stringify_1(x)	#x
> +#define __stringify(x)		__stringify_1(x)
>  static std::map<const std::string, const void *> exported_funcs =
>  {
> -#define EXPORT(f) {#f, (const void *)&f}
> +#define EXPORT(f) {__stringify(f), (const void *)&f}
>  	EXPORT(test__clang_callback),
>  	EXPORT(printf),
>  	EXPORT(puts),
> +	EXPORT(JIT_HELPER_FUNC_NAME(map_update_elem)),
> +	EXPORT(JIT_HELPER_FUNC_NAME(map_lookup_elem)),
> +	EXPORT(JIT_HELPER_FUNC_NAME(map_get_next_key)),
> +	EXPORT(JIT_HELPER_FUNC_NAME(map_pin)),
>  #undef EXPORT
...
> +#define PARAMS(args...) args
> +#define DEFINE_JIT_BPF_MAP_HELPER(name, proto, args)			\
> +	JIT_BPF_MAP_HELPER(name, proto) {				\
> +		int map_fd = get_bpf_map_fd(ctx, map);			\
> +									\
> +		if (map_fd < 0)						\
> +			return map_fd;					\
> +		return bpf_map_##name(map_fd, args);			\
> +	}
> +
> +DEFINE_JIT_BPF_MAP_HELPER(update_elem,
> +			  PARAMS(void *key, void *value, u64 flags),
> +			  PARAMS(key, value, flags))

the naming and approach to exports look good to me.
Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 01/30] tools lib bpf: Add missing BPF functions
  2016-11-26  7:03 ` [PATCH v3 01/30] tools lib bpf: Add missing BPF functions Wang Nan
@ 2016-11-26 17:10   ` Alexei Starovoitov
  2016-12-02 10:37   ` [tip:perf/core] " tip-bot for Wang Nan
  1 sibling, 0 replies; 73+ messages in thread
From: Alexei Starovoitov @ 2016-11-26 17:10 UTC (permalink / raw)
  To: Wang Nan; +Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe

On Sat, Nov 26, 2016 at 07:03:25AM +0000, Wang Nan wrote:
> Add more BPF map operations to libbpf. Also add bpf_obj_{pin,get}(). They
> can be used on not only BPF maps but also BPF programs.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Alexei Starovoitov <ast@fb.com>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Joe Stringer <joe@ovn.org>
> Cc: Li Zefan <lizefan@huawei.com>
> ---
>  tools/lib/bpf/bpf.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  tools/lib/bpf/bpf.h |  7 +++++++
>  2 files changed, 63 insertions(+)
> 
> diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
> index 4212ed6..8143536 100644
> --- a/tools/lib/bpf/bpf.c
> +++ b/tools/lib/bpf/bpf.c
> @@ -110,3 +110,59 @@ int bpf_map_update_elem(int fd, void *key, void *value,
>  
>  	return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
>  }
> +
> +int bpf_map_lookup_elem(int fd, void *key, void *value)
> +{
> +	union bpf_attr attr;
> +
> +	bzero(&attr, sizeof(attr));
> +	attr.map_fd = fd;
> +	attr.key = ptr_to_u64(key);
> +	attr.value = ptr_to_u64(value);
> +
> +	return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
> +}

Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 02/30] tools lib bpf: Add private field for bpf_object
  2016-11-26  7:03 ` [PATCH v3 02/30] tools lib bpf: Add private field for bpf_object Wang Nan
@ 2016-11-26 17:11   ` Alexei Starovoitov
  2016-12-02 10:37   ` [tip:perf/core] " tip-bot for Wang Nan
  1 sibling, 0 replies; 73+ messages in thread
From: Alexei Starovoitov @ 2016-11-26 17:11 UTC (permalink / raw)
  To: Wang Nan; +Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe

On Sat, Nov 26, 2016 at 07:03:26AM +0000, Wang Nan wrote:
> Similar to other classes defined in libbpf.h (map and program), allow
> 'object' class has its own private data.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Alexei Starovoitov <ast@fb.com>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Li Zefan <lizefan@huawei.com>
> ---
>  tools/lib/bpf/libbpf.c | 23 +++++++++++++++++++++++
>  tools/lib/bpf/libbpf.h |  5 +++++
>  2 files changed, 28 insertions(+)
> 
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 96a2b2f..866d5cd 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -229,6 +229,10 @@ struct bpf_object {
>  	 * all objects.
>  	 */
>  	struct list_head list;
> +
> +	void *priv;
> +	bpf_object_clear_priv_t clear_priv;
> +
>  	char path[];
>  };

Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 03/30] tools lib bpf: Retrive bpf_map through offset of bpf_map_def
  2016-11-26  7:03 ` [PATCH v3 03/30] tools lib bpf: Retrive bpf_map through offset of bpf_map_def Wang Nan
@ 2016-11-26 17:12   ` Alexei Starovoitov
  2016-12-02 10:38   ` [tip:perf/core] " tip-bot for Wang Nan
  1 sibling, 0 replies; 73+ messages in thread
From: Alexei Starovoitov @ 2016-11-26 17:12 UTC (permalink / raw)
  To: Wang Nan
  Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe,
	Alexei Starovoitov, Jiri Olsa

On Sat, Nov 26, 2016 at 07:03:27AM +0000, Wang Nan wrote:
> Add a new API to libbpf, caller is able to get bpf_map through the
> offset of bpf_map_def to 'maps' section.
> 
> The API will be used to help jitted perf hook code find fd of a map.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
...
> +struct bpf_map *
> +bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset)
> +{
> +	int i;
> +
> +	for (i = 0; i < obj->nr_maps; i++) {
> +		if (obj->maps[i].offset == offset)
> +			return &obj->maps[i];
> +	}
> +	return ERR_PTR(-ENOENT);
> +}

Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-11-26  7:03 ` [PATCH v3 10/30] perf clang: Add builtin clang support ant test case Wang Nan
@ 2016-11-26 17:17   ` Alexei Starovoitov
  2016-11-28  7:41     ` Wangnan (F)
  2016-12-02 15:44   ` Arnaldo Carvalho de Melo
  2016-12-06  8:23   ` [tip:perf/core] " tip-bot for Wang Nan
  2 siblings, 1 reply; 73+ messages in thread
From: Alexei Starovoitov @ 2016-11-26 17:17 UTC (permalink / raw)
  To: Wang Nan
  Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe, Jiri Olsa

On Sat, Nov 26, 2016 at 07:03:34AM +0000, Wang Nan wrote:
> Add basic clang support in clang.cpp and test__clang() testcase. The
> first testcase checks if builtin clang is able to generate LLVM IR.
> 
> tests/clang.c is a proxy. Real testcase resides in
> utils/c++/clang-test.cpp in c++ and exports C interface to perf test
> subsystem.
> 
> Test result:
> 
>    $ perf test -v clang
>    51: Test builtin clang support                               :
>    51.1: Test builtin clang compile C source to IR              :
>    --- start ---
>    test child forked, pid 13215
>    test child finished with 0
>    ---- end ----
>    Test builtin clang support subtest 0: Ok
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
...
> +static CompilerInvocation *
> +createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
> +{
> +	llvm::opt::ArgStringList CCArgs {
> +		"-cc1",
> +		"-triple", "bpf-pc-linux",
> +		"-fsyntax-only",
> +		"-ferror-limit", "19",
> +		"-fmessage-length", "127",

why such limits?

> +		"-O2",
> +		"-nostdsysteminc",
> +		"-nobuiltininc",
> +		"-vectorize-loops",
> +		"-vectorize-slp",

why above two flags are needed?

> +		"-Wno-unused-value",
> +		"-Wno-pointer-sign",

these two -Wno makes sense. please add the comment to explain the reasons.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 14/30] perf clang: Support compile IR to BPF object and add testcase
  2016-11-26  7:03 ` [PATCH v3 14/30] perf clang: Support compile IR to BPF object and add testcase Wang Nan
@ 2016-11-26 17:25   ` Alexei Starovoitov
  2016-11-28  6:32     ` Wangnan (F)
  2016-12-06  8:26   ` [tip:perf/core] " tip-bot for Wang Nan
  1 sibling, 1 reply; 73+ messages in thread
From: Alexei Starovoitov @ 2016-11-26 17:25 UTC (permalink / raw)
  To: Wang Nan
  Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe, Jiri Olsa

On Sat, Nov 26, 2016 at 07:03:38AM +0000, Wang Nan wrote:
> getBPFObjectFromModule() is introduced to compile LLVM IR(Module)
> to BPF object. Add new testcase for it.
> 
> Test result:
>   $ ./buildperf/perf test -v clang
>   51: Test builtin clang support                               :
>   51.1: Test builtin clang compile C source to IR              :
>   --- start ---
>   test child forked, pid 21822
>   test child finished with 0
>   ---- end ----
>   Test builtin clang support subtest 0: Ok
>   51.2: Test builtin clang compile C source to ELF object      :
>   --- start ---
>   test child forked, pid 21823
>   test child finished with 0
>   ---- end ----
>   Test builtin clang support subtest 1: Ok
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
...
> +	legacy::PassManager PM;
> +	if (TargetMachine->addPassesToEmitFile(PM, ostream,
> +					       TargetMachine::CGFT_ObjectFile)) {
> +		llvm::errs() << "TargetMachine can't emit a file of this type\n";
> +		return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);;
> +	}
> +	PM.run(*Module);

I'm pretty sure you want to add FunctionInlingPass as well otherwise
I think llvm won't be doing much inlining and only very very simple
programs will compile fine. See what we did on bcc side.

Also did you consider skipping elf generation and using in memory
instead ? That will improve compile/run time.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions
  2016-11-26  7:03 ` [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions Wang Nan
@ 2016-11-26 17:29   ` Alexei Starovoitov
  2016-11-28  6:42     ` Wangnan (F)
  0 siblings, 1 reply; 73+ messages in thread
From: Alexei Starovoitov @ 2016-11-26 17:29 UTC (permalink / raw)
  To: Wang Nan
  Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe, Jiri Olsa

On Sat, Nov 26, 2016 at 07:03:44AM +0000, Wang Nan wrote:
> PerfModule::doJIT JIT compile perfhook functions and saves result into
> a map. Add a test case for it.
> 
> At this stage perfhook functions can do no useful things because they
> can't invoke external functions and can't return value. Following
> commits are going to make improvment.
> 
> Don't hook functions right after jitted because bpf_object is unavailable
> during jitting but it should be the context of jitted functions.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
...
> +	for (Function *F : JITFunctions) {
> +		JITSymbol sym = CompileLayer.findSymbol(F->getName().str(), true);
> +
> +		/*
> +		 * Type of F->getSection() is moving from
> +		 * const char * to StringRef.
> +		 * Convert it to std::string so we don't need
> +		 * consider this API change.
> +		 */
> +		std::string sec(F->getSection());
> +		std::string hook(&sec.c_str()[sizeof("perfhook:") - 1]);
> +		perf_hook_func_t func = (perf_hook_func_t)(intptr_t)sym.getAddress();
> +
> +		if (JITResult[hook])
> +			llvm::errs() << "Warning: multiple functions on hook "
> +				     << hook << ", only one is used\n";
> +		JITResult[hook] = func;
> +	}
> +	return 0;
> +}
> +
>  class ClangOptions {
>  	llvm::SmallString<PATH_MAX> FileName;
>  	llvm::SmallString<64> KVerDef;
> @@ -292,6 +359,10 @@ void perf_clang__init(void)
>  	LLVMInitializeBPFTarget();
>  	LLVMInitializeBPFTargetMC();
>  	LLVMInitializeBPFAsmPrinter();
> +
> +	llvm::InitializeNativeTarget();
> +	llvm::InitializeNativeTargetAsmPrinter();
> +	llvm::InitializeNativeTargetAsmParser();

Looks great. I bet a lot of people reading perf code
won't be able to understand what you're doing here.
Could you please add a design doc on how perf<->clang/llvm interaction
is done.

Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 19/30] perf clang jit: Insignt BPF and JIT functions in a Module
  2016-11-26  7:03 ` [PATCH v3 19/30] perf clang jit: Insignt BPF and JIT functions in a Module Wang Nan
@ 2016-11-26 17:32   ` Alexei Starovoitov
  0 siblings, 0 replies; 73+ messages in thread
From: Alexei Starovoitov @ 2016-11-26 17:32 UTC (permalink / raw)
  To: Wang Nan
  Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe, Jiri Olsa

On Sat, Nov 26, 2016 at 07:03:43AM +0000, Wang Nan wrote:
> Identify BPF functions, JIT functions and maps during init. Functions in
> section starting with "perfhook:" are JIT functions. They will be JIT
> compiled and hooked at perfhooks.
> 
> During init of PerfModule, mark JIT functions as AvailableExternallyLinkage.
> LLVM skips functions with linkage like this so they won't be compiled
> into BPF objects.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
...
> +void PerfModule::prepareBPF(void)
> +{
> +	for (llvm::Function *F : JITFunctions)
> +		F->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
> +	for (llvm::Function *F : BPFFunctions)
> +		F->setLinkage(llvm::GlobalValue::ExternalLinkage);
> +
> +}
> +
> +void PerfModule::prepareJIT(void)
> +{
> +	for (llvm::Function *F : BPFFunctions)
> +		F->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
> +	for (llvm::Function *F : JITFunctions)
> +		F->setLinkage(llvm::GlobalValue::ExternalLinkage);
> +
> +}

Nice trick.
Please document it in the perf+llvm design doc.

Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 26/30] perf clang: Link BPF functions declaration into perf
  2016-11-26  7:03 ` [PATCH v3 26/30] perf clang: Link BPF functions declaration into perf Wang Nan
@ 2016-11-26 17:40   ` Alexei Starovoitov
  2016-11-30 16:12     ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 73+ messages in thread
From: Alexei Starovoitov @ 2016-11-26 17:40 UTC (permalink / raw)
  To: Wang Nan
  Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe, Jiri Olsa

On Sat, Nov 26, 2016 at 07:03:50AM +0000, Wang Nan wrote:
> Use a shell script to generate BPF functions declarations from kernel
> source code, embed the generated header into a C string. Following
> commits will utilizes clang's virtual file system to automatically
> include this header to all BPF scripts.
> 
> The generated header is wrapped by a BUILTIN_CLANG_NO_DEFAULT_INCLUDE.
> This macro will be used by following commits to allow user disable this
> and other builtin includes.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Alexei Starovoitov <ast@fb.com>
> Cc: He Kuang <hekuang@huawei.com>
> Cc: Jiri Olsa <jolsa@kernel.org>
> Cc: Zefan Li <lizefan@huawei.com>
> Cc: pi3orama@163.com
> ---
>  tools/perf/util/c++/Build                |   1 +
>  tools/perf/util/c++/bpf-funcs-str.c      | 228 +++++++++++++++++++++++++++++++
>  tools/perf/util/c++/clang-bpf-includes.h |  12 ++
>  3 files changed, 241 insertions(+)
>  create mode 100644 tools/perf/util/c++/bpf-funcs-str.c
>  create mode 100644 tools/perf/util/c++/clang-bpf-includes.h
> 
> diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
> index 988fef1..bd71abf 100644
> --- a/tools/perf/util/c++/Build
> +++ b/tools/perf/util/c++/Build
> @@ -1,2 +1,3 @@
>  libperf-$(CONFIG_CLANGLLVM) += clang.o
>  libperf-$(CONFIG_CLANGLLVM) += clang-test.o
> +libperf-$(CONFIG_CLANGLLVM) += bpf-funcs-str.o
> diff --git a/tools/perf/util/c++/bpf-funcs-str.c b/tools/perf/util/c++/bpf-funcs-str.c
> new file mode 100644
> index 0000000..f6bcf76
> --- /dev/null
> +++ b/tools/perf/util/c++/bpf-funcs-str.c
> @@ -0,0 +1,228 @@
> +/*
> + * This file is generated by following script:
> + *
> + * #!/bin/bash
> + * TEMP_KBUILD=$(mktemp -d)
> + * KERNEL_DIR=$(pwd)
> + * OUTPUT=tools/perf/util/c++/bpf-funcs-str.c
> + * rm -rf $OUTPUT
> + * echo "Use temp dir: $TEMP_KBUILD"
> + * function finish()
> + * {
> + * 	rm -rf $TEMP_KBUILD
> + * }
> + * trap finish EXIT
> + * SRCLIST=$(find -name "*.c" | xargs grep bpf_func_proto -l)
> + * cd $TEMP_KBUILD
> + * yes '' | make -C $KERNEL_DIR O=`pwd` oldconfig
> + * cat << EOF >> ./.config
> + * CONFIG_BPF=y
> + * CONFIG_BPF_SYSCALL=y
> + * CONFIG_PERF_EVENTS=y
> + * CONFIG_SOCK_CGROUP_DATA=y
> + * EOF
> + * yes '' | make -C $KERNEL_DIR O=`pwd` oldconfig
> + * FIXOBJLIST=""
> + * for src in ${SRCLIST}
> + * do
> + * 	mkdir -p $(dirname $src)
> + * 	cat << EOF > "${src}-fix.c"
> + * #include <linux/init.h>
> + * #undef __init
> + * #define __init __attribute__((constructor))
> + * #include "`basename $src`"
> + * EOF
> + * 	if [ $(basename $src) == "syscall.c" ]
> + * 	then
> + * 		cat << EOF >> "${src}-fix.c"
> + * const struct bpf_verifier_ops *
> + * find_prog_type_export(enum bpf_prog_type type)
> + * {
> + * 	struct bpf_prog_aux aux;
> + * 	struct bpf_prog p = {.aux = &aux };
> + * 	if (find_prog_type(type, &p))
> + * 		return NULL;
> + * 	return p.aux->ops;
> + * }
> + * EOF
> + * 	fi
> + * 	FIXOBJLIST="$FIXOBJLIST ${src}-fix.o"
> + * done
> + * function dolink()
> + * {
> + * 	touch ./syms.c
> + * 	echo gcc kernel/bpf/main.o ./syms.c $FIXOBJLIST -o ./gen
> + * 	gcc kernel/bpf/main.o ./syms.c $FIXOBJLIST -o ./gen
> + * }
> + * MAIN=kernel/bpf/main.c
> + * cat << EOF > $MAIN
> + * #include <uapi/linux/bpf.h>
> + * #include <linux/bpf.h>
> + * struct bpf_func {
> + *   const char *name;
> + *   int id;
> + * } bpf_funcs[] = {
> + * EOF
> + * grep '^[[:space:]]BPF_FUNC_[^ ]*,' $KERNEL_DIR/include/uapi/linux/bpf.h | \
> + * 	sed -e 's/.*BPF_FUNC_\([^,]*\),.*$/\1/g' | \
> + * 	xargs -n 1 sh -c 'echo {.name = \"$1\", .id = BPF_FUNC_$1}, >> '"$MAIN" sh
> + * cat << EOF >> $MAIN

This is pretty fragile and already broken.
Please just hardcode them as-is. There is no need to be so fancy.

> +"static void *(*bpf_map_lookup_elem)(void *, void *) = (void *)1;\n"
> +"static long (*bpf_map_update_elem)(void *, void *, void *, unsigned long) = (void *)2;\n"
> +"static long (*bpf_map_delete_elem)(void *, void *) = (void *)3;\n"

just hard code this way.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 14/30] perf clang: Support compile IR to BPF object and add testcase
  2016-11-26 17:25   ` Alexei Starovoitov
@ 2016-11-28  6:32     ` Wangnan (F)
  2016-11-28 10:31       ` Wangnan (F)
  0 siblings, 1 reply; 73+ messages in thread
From: Wangnan (F) @ 2016-11-28  6:32 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe, Jiri Olsa



On 2016/11/27 1:25, Alexei Starovoitov wrote:
> On Sat, Nov 26, 2016 at 07:03:38AM +0000, Wang Nan wrote:
>> getBPFObjectFromModule() is introduced to compile LLVM IR(Module)
>> to BPF object. Add new testcase for it.
>>
>> Test result:
>>    $ ./buildperf/perf test -v clang
>>    51: Test builtin clang support                               :
>>    51.1: Test builtin clang compile C source to IR              :
>>    --- start ---
>>    test child forked, pid 21822
>>    test child finished with 0
>>    ---- end ----
>>    Test builtin clang support subtest 0: Ok
>>    51.2: Test builtin clang compile C source to ELF object      :
>>    --- start ---
>>    test child forked, pid 21823
>>    test child finished with 0
>>    ---- end ----
>>    Test builtin clang support subtest 1: Ok
>>
>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> ...
>> +	legacy::PassManager PM;
>> +	if (TargetMachine->addPassesToEmitFile(PM, ostream,
>> +					       TargetMachine::CGFT_ObjectFile)) {
>> +		llvm::errs() << "TargetMachine can't emit a file of this type\n";
>> +		return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);;
>> +	}
>> +	PM.run(*Module);
> I'm pretty sure you want to add FunctionInlingPass as well otherwise
> I think llvm won't be doing much inlining and only very very simple
> programs will compile fine. See what we did on bcc side.

Thank you for your information. I though inlining should be done during
C to IR phase, and we have use -O2 for it. Let me check it.

> Also did you consider skipping elf generation and using in memory
> instead ? That will improve compile/run time.
>

Maybe in future work? Current design reuse libelf and bpf-loader for
loading BPF code. Skipping ELF generation make compiling faster, but
require another loader to be coexist with bpf-loader.c, or we need
a new libbpf. In my current experience, outputting ELF is not so slow
for both server and smartphone.

Thank you.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions
  2016-11-26 17:29   ` Alexei Starovoitov
@ 2016-11-28  6:42     ` Wangnan (F)
  0 siblings, 0 replies; 73+ messages in thread
From: Wangnan (F) @ 2016-11-28  6:42 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe, Jiri Olsa



On 2016/11/27 1:29, Alexei Starovoitov wrote:
> On Sat, Nov 26, 2016 at 07:03:44AM +0000, Wang Nan wrote:
>> PerfModule::doJIT JIT compile perfhook functions and saves result into
>> a map. Add a test case for it.
>>
>> At this stage perfhook functions can do no useful things because they
>> can't invoke external functions and can't return value. Following
>> commits are going to make improvment.
>>
>> Don't hook functions right after jitted because bpf_object is unavailable
>> during jitting but it should be the context of jitted functions.
>>
>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> ...
>> +	for (Function *F : JITFunctions) {
>> +		JITSymbol sym = CompileLayer.findSymbol(F->getName().str(), true);
>> +
>> +		/*
>> +		 * Type of F->getSection() is moving from
>> +		 * const char * to StringRef.
>> +		 * Convert it to std::string so we don't need
>> +		 * consider this API change.
>> +		 */
>> +		std::string sec(F->getSection());
>> +		std::string hook(&sec.c_str()[sizeof("perfhook:") - 1]);
>> +		perf_hook_func_t func = (perf_hook_func_t)(intptr_t)sym.getAddress();
>> +
>> +		if (JITResult[hook])
>> +			llvm::errs() << "Warning: multiple functions on hook "
>> +				     << hook << ", only one is used\n";
>> +		JITResult[hook] = func;
>> +	}
>> +	return 0;
>> +}
>> +
>>   class ClangOptions {
>>   	llvm::SmallString<PATH_MAX> FileName;
>>   	llvm::SmallString<64> KVerDef;
>> @@ -292,6 +359,10 @@ void perf_clang__init(void)
>>   	LLVMInitializeBPFTarget();
>>   	LLVMInitializeBPFTargetMC();
>>   	LLVMInitializeBPFAsmPrinter();
>> +
>> +	llvm::InitializeNativeTarget();
>> +	llvm::InitializeNativeTargetAsmPrinter();
>> +	llvm::InitializeNativeTargetAsmParser();
> Looks great. I bet a lot of people reading perf code
> won't be able to understand what you're doing here.
> Could you please add a design doc on how perf<->clang/llvm interaction
> is done.

I'll put a perf-clang.txt in tools/perf/Documentation.

Thank you.

> Acked-by: Alexei Starovoitov <ast@kernel.org>
>

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-11-26 17:17   ` Alexei Starovoitov
@ 2016-11-28  7:41     ` Wangnan (F)
  0 siblings, 0 replies; 73+ messages in thread
From: Wangnan (F) @ 2016-11-28  7:41 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe, Jiri Olsa



On 2016/11/27 1:17, Alexei Starovoitov wrote:
> On Sat, Nov 26, 2016 at 07:03:34AM +0000, Wang Nan wrote:
>> Add basic clang support in clang.cpp and test__clang() testcase. The
>> first testcase checks if builtin clang is able to generate LLVM IR.
>>
>> tests/clang.c is a proxy. Real testcase resides in
>> utils/c++/clang-test.cpp in c++ and exports C interface to perf test
>> subsystem.
>>
>> Test result:
>>
>>     $ perf test -v clang
>>     51: Test builtin clang support                               :
>>     51.1: Test builtin clang compile C source to IR              :
>>     --- start ---
>>     test child forked, pid 13215
>>     test child finished with 0
>>     ---- end ----
>>     Test builtin clang support subtest 0: Ok
>>
>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> ...
>> +static CompilerInvocation *
>> +createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
>> +{
>> +	llvm::opt::ArgStringList CCArgs {
>> +		"-cc1",
>> +		"-triple", "bpf-pc-linux",
>> +		"-fsyntax-only",
>> +		"-ferror-limit", "19",
>> +		"-fmessage-length", "127",
> why such limits?
>
>> +		"-O2",
>> +		"-nostdsysteminc",
>> +		"-nobuiltininc",
>> +		"-vectorize-loops",
>> +		"-vectorize-slp",

Thank you for pointing these out. These arguments are get by analysising
the clang example:

https://llvm.org/svn/llvm-project/cfe/branches/ggreif/CallInst-operands/examples/clang-interpreter/main.cpp

The above example create a C compiler using clang::driver::Driver (bcc 
also uses driver).
I form the argument list according to arglist the driver created for its CI,
and leaves arguments I'm not quite sure unchanged.

> why above two flags are needed?
>
>> +		"-Wno-unused-value",
>> +		"-Wno-pointer-sign",
> these two -Wno makes sense. please add the comment to explain the reasons.
>
They are inherited from samples/bpf/Makefile to suppress some warning
when include kernel headers.

Thank you.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 14/30] perf clang: Support compile IR to BPF object and add testcase
  2016-11-28  6:32     ` Wangnan (F)
@ 2016-11-28 10:31       ` Wangnan (F)
  2016-11-28 19:33         ` Alexei Starovoitov
  0 siblings, 1 reply; 73+ messages in thread
From: Wangnan (F) @ 2016-11-28 10:31 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe, Jiri Olsa



On 2016/11/28 14:32, Wangnan (F) wrote:
>
>
> On 2016/11/27 1:25, Alexei Starovoitov wrote:
>> On Sat, Nov 26, 2016 at 07:03:38AM +0000, Wang Nan wrote:
>>> getBPFObjectFromModule() is introduced to compile LLVM IR(Module)
>>> to BPF object. Add new testcase for it.
>>>
>>> Test result:
>>>    $ ./buildperf/perf test -v clang
>>>    51: Test builtin clang support                               :
>>>    51.1: Test builtin clang compile C source to IR              :
>>>    --- start ---
>>>    test child forked, pid 21822
>>>    test child finished with 0
>>>    ---- end ----
>>>    Test builtin clang support subtest 0: Ok
>>>    51.2: Test builtin clang compile C source to ELF object      :
>>>    --- start ---
>>>    test child forked, pid 21823
>>>    test child finished with 0
>>>    ---- end ----
>>>    Test builtin clang support subtest 1: Ok
>>>
>>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
>> ...
>>> +    legacy::PassManager PM;
>>> +    if (TargetMachine->addPassesToEmitFile(PM, ostream,
>>> +                           TargetMachine::CGFT_ObjectFile)) {
>>> +        llvm::errs() << "TargetMachine can't emit a file of this 
>>> type\n";
>>> +        return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);;
>>> +    }
>>> +    PM.run(*Module);
>> I'm pretty sure you want to add FunctionInlingPass as well otherwise
>> I think llvm won't be doing much inlining and only very very simple
>> programs will compile fine. See what we did on bcc side.
>
> Thank you for your information. I though inlining should be done during
> C to IR phase, and we have use -O2 for it. Let me check it.
>

I did a simple test. It seems even without FunctionInliningPass clang/llvm
can inline static function with no problem. For example, in the sample code
in the cover letter, extract a static function like this:

   static void inc_counter(u64 id)
   {
       u64 *counter;

       counter = bpf_map_lookup_elem(&syscall_counter, &id);
       if (!counter) {
           u64 value = 1;
           bpf_map_update_elem(&syscall_counter, &id, &value, 0);
           return;
       }
       __sync_fetch_and_add(counter, 1);
       return;
   }

Then enable llvm.dump-obj = true in ~/.perfconfig so we can see the
resuling ELF object.

The script worked correctly. readelf report:

  $ readelf -a ./count_syscalls.o | grep inc_counter
  $

Inserting output command into PerfModule::prepareBPF and 
PerfModule::prepareJIT
to print names of functions, can't see inc_counter.

Then remove -O2 in cflags in createCompilerInvocation. Result:

# ./perf record -e ./count_syscalls.c -a sleep 1
LLVM ERROR: Cannot select: t38: ch,glue = BPFISD::CALL t37, t31, 
Register:i64 %R1, Register:i64 %R2, t37:1
   t31: i64,ch = load<LD8[@bpf_map_lookup_elem]> t51, t58, undef:i64
     t58: i64 = BPFISD::Wrapper TargetGlobalAddress:i64<i8* (i8*, i8*)** 
@bpf_map_lookup_elem> 0
       t57: i64 = TargetGlobalAddress<i8* (i8*, i8*)** 
@bpf_map_lookup_elem> 0
     t5: i64 = undef
   t34: i64 = Register %R1
   t36: i64 = Register %R2
   t37: ch,glue = CopyToReg t35, Register:i64 %R2, FrameIndex:i64<5>, t35:1
     t36: i64 = Register %R2
     t8: i64 = FrameIndex<5>
     t35: ch,glue = CopyToReg t33, Register:i64 %R1, t56
       t34: i64 = Register %R1
       t56: i64 = BPFISD::Wrapper 
TargetGlobalAddress:i64<%struct.bpf_map_def* @GVALS> 0
         t55: i64 = TargetGlobalAddress<%struct.bpf_map_def* @GVALS> 0
In function: func

Don't know whether -O2 imply inlining.

In bcc, you not only use FunctionInlining, but also add AlwaysInlinerPass
and use populateModulePassManager to append other optimization. I tried to
minimic your code, but it seems the perfhook functions are optimized out
by some optimization added by populateModulePassManager.

Although not quite clear, I'll make following change. Please help me
check it.

Thank you.

diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index d05ab6f..d6d1959 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -22,6 +22,8 @@
  #include "llvm/Support/TargetSelect.h"
  #include "llvm/Target/TargetMachine.h"
  #include "llvm/Target/TargetOptions.h"
+#include "llvm-c/Transforms/IPO.h"
+#include "llvm/Transforms/IPO.h"
  #include <memory>

  #include "clang.h"
@@ -133,6 +135,13 @@ getBPFObjectFromModule(llvm::Module *Module)
         raw_svector_ostream ostream(*Buffer);

         legacy::PassManager PM;
+
+    PM.add(createFunctionInliningPass());
+    /*
+     * LLVM is changing its interface. Use a stable workaround.
+     */
+ LLVMAddAlwaysInlinerPass(reinterpret_cast<LLVMPassManagerRef>(&PM));
+
      if (TargetMachine->addPassesToEmitFile(PM, ostream,
                             TargetMachine::CGFT_ObjectFile)) {
          llvm::errs() << "TargetMachine can't emit a file of this type\n";

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 14/30] perf clang: Support compile IR to BPF object and add testcase
  2016-11-28 10:31       ` Wangnan (F)
@ 2016-11-28 19:33         ` Alexei Starovoitov
  0 siblings, 0 replies; 73+ messages in thread
From: Alexei Starovoitov @ 2016-11-28 19:33 UTC (permalink / raw)
  To: Wangnan (F)
  Cc: acme, ast, lizefan, hekuang, linux-kernel, pi3orama, joe, Jiri Olsa

On Mon, Nov 28, 2016 at 06:31:11PM +0800, Wangnan (F) wrote:
> 
> 
> On 2016/11/28 14:32, Wangnan (F) wrote:
> >
> >
> >On 2016/11/27 1:25, Alexei Starovoitov wrote:
> >>On Sat, Nov 26, 2016 at 07:03:38AM +0000, Wang Nan wrote:
> >>>getBPFObjectFromModule() is introduced to compile LLVM IR(Module)
> >>>to BPF object. Add new testcase for it.
> >>>
> >>>Test result:
> >>>   $ ./buildperf/perf test -v clang
> >>>   51: Test builtin clang support                               :
> >>>   51.1: Test builtin clang compile C source to IR              :
> >>>   --- start ---
> >>>   test child forked, pid 21822
> >>>   test child finished with 0
> >>>   ---- end ----
> >>>   Test builtin clang support subtest 0: Ok
> >>>   51.2: Test builtin clang compile C source to ELF object      :
> >>>   --- start ---
> >>>   test child forked, pid 21823
> >>>   test child finished with 0
> >>>   ---- end ----
> >>>   Test builtin clang support subtest 1: Ok
> >>>
> >>>Signed-off-by: Wang Nan <wangnan0@huawei.com>
> >>...
> >>>+    legacy::PassManager PM;
> >>>+    if (TargetMachine->addPassesToEmitFile(PM, ostream,
> >>>+                           TargetMachine::CGFT_ObjectFile)) {
> >>>+        llvm::errs() << "TargetMachine can't emit a file of this
> >>>type\n";
> >>>+        return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);;
> >>>+    }
> >>>+    PM.run(*Module);
> >>I'm pretty sure you want to add FunctionInlingPass as well otherwise
> >>I think llvm won't be doing much inlining and only very very simple
> >>programs will compile fine. See what we did on bcc side.
> >
> >Thank you for your information. I though inlining should be done during
> >C to IR phase, and we have use -O2 for it. Let me check it.
> >
> 
> I did a simple test. It seems even without FunctionInliningPass clang/llvm
> can inline static function with no problem. For example, in the sample code
> in the cover letter, extract a static function like this:
> 
>   static void inc_counter(u64 id)
>   {
>       u64 *counter;
> 
>       counter = bpf_map_lookup_elem(&syscall_counter, &id);
>       if (!counter) {
>           u64 value = 1;
>           bpf_map_update_elem(&syscall_counter, &id, &value, 0);
>           return;
>       }
>       __sync_fetch_and_add(counter, 1);
>       return;
>   }
> 
> Then enable llvm.dump-obj = true in ~/.perfconfig so we can see the
> resuling ELF object.
> 
> The script worked correctly. readelf report:
> 
>  $ readelf -a ./count_syscalls.o | grep inc_counter
>  $
> 
> Inserting output command into PerfModule::prepareBPF and
> PerfModule::prepareJIT
> to print names of functions, can't see inc_counter.
> 
> Then remove -O2 in cflags in createCompilerInvocation. Result:
> 
> # ./perf record -e ./count_syscalls.c -a sleep 1
> LLVM ERROR: Cannot select: t38: ch,glue = BPFISD::CALL t37, t31,
> Register:i64 %R1, Register:i64 %R2, t37:1
>   t31: i64,ch = load<LD8[@bpf_map_lookup_elem]> t51, t58, undef:i64
>     t58: i64 = BPFISD::Wrapper TargetGlobalAddress:i64<i8* (i8*, i8*)**
> @bpf_map_lookup_elem> 0
>       t57: i64 = TargetGlobalAddress<i8* (i8*, i8*)** @bpf_map_lookup_elem>
> 0
>     t5: i64 = undef
>   t34: i64 = Register %R1
>   t36: i64 = Register %R2
>   t37: ch,glue = CopyToReg t35, Register:i64 %R2, FrameIndex:i64<5>, t35:1
>     t36: i64 = Register %R2
>     t8: i64 = FrameIndex<5>
>     t35: ch,glue = CopyToReg t33, Register:i64 %R1, t56
>       t34: i64 = Register %R1
>       t56: i64 = BPFISD::Wrapper
> TargetGlobalAddress:i64<%struct.bpf_map_def* @GVALS> 0
>         t55: i64 = TargetGlobalAddress<%struct.bpf_map_def* @GVALS> 0
> In function: func

yeah. we need to improve the above 'cannot select' error.
please send a patch if you have spare cycles.
I'm planning to add more meaningful warnings to backend.
In most cases backend knows that certain program will not pass
the verifier, so it's better to warn about that early.

> Don't know whether -O2 imply inlining.
> 
> In bcc, you not only use FunctionInlining, but also add AlwaysInlinerPass
> and use populateModulePassManager to append other optimization. I tried to
> minimic your code, but it seems the perfhook functions are optimized out
> by some optimization added by populateModulePassManager.
> 
> Although not quite clear, I'll make following change. Please help me
> check it.

well, if you see inlining happening without explicitly specifying
the pass, then just keep it as-is.
Though please double check that backend is doing inling.
May be in your simple test front-end inlined it.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 26/30] perf clang: Link BPF functions declaration into perf
  2016-11-26 17:40   ` Alexei Starovoitov
@ 2016-11-30 16:12     ` Arnaldo Carvalho de Melo
  2016-12-01  1:56       ` [PATCH v3 26/30 - cleanup] " Wang Nan
  0 siblings, 1 reply; 73+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-11-30 16:12 UTC (permalink / raw)
  To: Wang Nan
  Cc: Alexei Starovoitov, ast, lizefan, hekuang, linux-kernel,
	pi3orama, joe, Jiri Olsa, acme

Em Sat, Nov 26, 2016 at 09:40:41AM -0800, Alexei Starovoitov escreveu:
> On Sat, Nov 26, 2016 at 07:03:50AM +0000, Wang Nan wrote:
> > + * } bpf_funcs[] = {
> > + * EOF
> > + * grep '^[[:space:]]BPF_FUNC_[^ ]*,' $KERNEL_DIR/include/uapi/linux/bpf.h | \
> > + * 	sed -e 's/.*BPF_FUNC_\([^,]*\),.*$/\1/g' | \
> > + * 	xargs -n 1 sh -c 'echo {.name = \"$1\", .id = BPF_FUNC_$1}, >> '"$MAIN" sh
> > + * cat << EOF >> $MAIN
> 
> This is pretty fragile and already broken.
> Please just hardcode them as-is. There is no need to be so fancy.
> 
> > +"static void *(*bpf_map_lookup_elem)(void *, void *) = (void *)1;\n"
> > +"static long (*bpf_map_update_elem)(void *, void *, void *, unsigned long) = (void *)2;\n"
> > +"static long (*bpf_map_delete_elem)(void *, void *) = (void *)3;\n"
> 
> just hard code this way.

Wang, can you please resend this? I'm trying to process this patchkit,
but will take some time to get to this 26th patch.

- Arnaldo

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [PATCH v3 26/30 - cleanup] perf clang: Link BPF functions declaration into perf
  2016-11-30 16:12     ` Arnaldo Carvalho de Melo
@ 2016-12-01  1:56       ` Wang Nan
  0 siblings, 0 replies; 73+ messages in thread
From: Wang Nan @ 2016-12-01  1:56 UTC (permalink / raw)
  To: acme
  Cc: linux-kernel, joe, Wang Nan, Alexei Starovoitov, He Kuang,
	Jiri Olsa, Zefan Li, pi3orama

Hardcode BPF functions declarations. Following commits will utilizes
clang's virtual file system to automatically include this header to
all BPF scripts.

The generated header is wrapped by a BUILTIN_CLANG_NO_DEFAULT_INCLUDE.
This macro will be used by following commits to allow user disable this
feature.

The C string looks ugly and heavily uses magic numbers because the
header is designed to be included automatically at very first, makes
any dependency or potential conflict harmful. Actually it is
automatically generated using a script:
https://patchwork.kernel.org/patch/9350221
However, that script is fragile so not included by this commit.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/c++/Build                |  1 +
 tools/perf/util/c++/bpf-funcs-str.c      | 49 ++++++++++++++++++++++++++++++++
 tools/perf/util/c++/clang-bpf-includes.h | 12 ++++++++
 3 files changed, 62 insertions(+)
 create mode 100644 tools/perf/util/c++/bpf-funcs-str.c
 create mode 100644 tools/perf/util/c++/clang-bpf-includes.h

diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
index 988fef1..bd71abf 100644
--- a/tools/perf/util/c++/Build
+++ b/tools/perf/util/c++/Build
@@ -1,2 +1,3 @@
 libperf-$(CONFIG_CLANGLLVM) += clang.o
 libperf-$(CONFIG_CLANGLLVM) += clang-test.o
+libperf-$(CONFIG_CLANGLLVM) += bpf-funcs-str.o
diff --git a/tools/perf/util/c++/bpf-funcs-str.c b/tools/perf/util/c++/bpf-funcs-str.c
new file mode 100644
index 0000000..ab1a0e3
--- /dev/null
+++ b/tools/perf/util/c++/bpf-funcs-str.c
@@ -0,0 +1,49 @@
+#include "clang-bpf-includes.h"
+const char clang_builtin_bpf_funcs_str[] =
+"#ifdef BUILTIN_CLANG_DEFAULT_INCLUDE\n"
+"#ifndef BPF_FUNCS_DEFINED\n"
+"#define BPF_FUNCS_DEFINED\n"
+"static void *(*bpf_map_lookup_elem)(void *, void *) = (void *)1;\n"
+"static long (*bpf_map_update_elem)(void *, void *, void *, unsigned long) = (void *)2;\n"
+"static long (*bpf_map_delete_elem)(void *, void *) = (void *)3;\n"
+"static long (*bpf_probe_read)(void *, unsigned long, unsigned long) = (void *)4;\n"
+"static long (*bpf_ktime_get_ns)(void) = (void *)5;\n"
+"static long (*bpf_trace_printk)(void *, unsigned long, ...) = (void *)6;\n"
+"static long (*bpf_get_prandom_u32)(void) = (void *)7;\n"
+"static long (*bpf_get_smp_processor_id)(void) = (void *)8;\n"
+"static long (*bpf_skb_store_bytes)(void *, unsigned long, void *, unsigned long, unsigned long) = (void *)9;\n"
+"static long (*bpf_l3_csum_replace)(void *, unsigned long, unsigned long, unsigned long, unsigned long) = (void *)10;\n"
+"static long (*bpf_l4_csum_replace)(void *, unsigned long, unsigned long, unsigned long, unsigned long) = (void *)11;\n"
+"static void (*bpf_tail_call)(void *, void *, unsigned long) = (void *)12;\n"
+"static long (*bpf_clone_redirect)(void *, unsigned long, unsigned long) = (void *)13;\n"
+"static long (*bpf_get_current_pid_tgid)(void) = (void *)14;\n"
+"static long (*bpf_get_current_uid_gid)(void) = (void *)15;\n"
+"static long (*bpf_get_current_comm)(void *, unsigned long) = (void *)16;\n"
+"static long (*bpf_get_cgroup_classid)(void *) = (void *)17;\n"
+"static long (*bpf_skb_vlan_push)(void *, unsigned long, unsigned long) = (void *)18;\n"
+"static long (*bpf_skb_vlan_pop)(void *) = (void *)19;\n"
+"static long (*bpf_skb_get_tunnel_key)(void *, void *, unsigned long, unsigned long) = (void *)20;\n"
+"static long (*bpf_skb_set_tunnel_key)(void *, void *, unsigned long, unsigned long) = (void *)21;\n"
+"static long (*bpf_perf_event_read)(void *, unsigned long) = (void *)22;\n"
+"static long (*bpf_redirect)(unsigned long, unsigned long) = (void *)23;\n"
+"static long (*bpf_get_route_realm)(void *) = (void *)24;\n"
+"static long (*bpf_perf_event_output)(void *, void *, unsigned long, void *, unsigned long) = (void *)25;\n"
+"static long (*bpf_skb_load_bytes)(void *, unsigned long, void *, unsigned long) = (void *)26;\n"
+"static long (*bpf_get_stackid)(void *, void *, unsigned long) = (void *)27;\n"
+"static long (*bpf_csum_diff)(void *, unsigned long, void *, unsigned long, unsigned long) = (void *)28;\n"
+"static long (*bpf_skb_get_tunnel_opt)(void *, void *, unsigned long) = (void *)29;\n"
+"static long (*bpf_skb_set_tunnel_opt)(void *, void *, unsigned long) = (void *)30;\n"
+"static long (*bpf_skb_change_proto)(void *, unsigned long, unsigned long) = (void *)31;\n"
+"static long (*bpf_skb_change_type)(void *, unsigned long) = (void *)32;\n"
+"static long (*bpf_skb_under_cgroup)(void *, void *, unsigned long) = (void *)33;\n"
+"static long (*bpf_get_hash_recalc)(void *) = (void *)34;\n"
+"static long (*bpf_get_current_task)(void) = (void *)35;\n"
+"static long (*bpf_probe_write_user)(unsigned long, void *, unsigned long) = (void *)36;\n"
+"static long (*bpf_current_task_under_cgroup)(void *, unsigned long) = (void *)37;\n"
+"static long (*bpf_skb_change_tail)(void *, unsigned long, unsigned long) = (void *)38;\n"
+"static long (*bpf_skb_pull_data)(void *, unsigned long) = (void *)39;\n"
+"static long (*bpf_csum_update)(void *, unsigned long) = (void *)40;\n"
+"static long (*bpf_set_hash_invalid)(void *) = (void *)41;\n"
+"#endif\n"
+"#endif\n"
+;
diff --git a/tools/perf/util/c++/clang-bpf-includes.h b/tools/perf/util/c++/clang-bpf-includes.h
new file mode 100644
index 0000000..385a5bb
--- /dev/null
+++ b/tools/perf/util/c++/clang-bpf-includes.h
@@ -0,0 +1,12 @@
+#ifndef CLANG_BPF_INCLUDS_H
+#define CLANG_BPF_INCLUDS_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char clang_builtin_bpf_funcs_str[];
+
+#ifdef __cplusplus
+}
+#endif
+#endif
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] tools lib bpf: Add missing BPF functions
  2016-11-26  7:03 ` [PATCH v3 01/30] tools lib bpf: Add missing BPF functions Wang Nan
  2016-11-26 17:10   ` Alexei Starovoitov
@ 2016-12-02 10:37   ` tip-bot for Wang Nan
  1 sibling, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-02 10:37 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: joe, tglx, acme, ast, hekuang, hpa, mingo, wangnan0, lizefan,
	linux-kernel

Commit-ID:  9742da0150788e6ea7796372c3e643f876a49741
Gitweb:     http://git.kernel.org/tip/9742da0150788e6ea7796372c3e643f876a49741
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:25 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 29 Nov 2016 12:09:36 -0300

tools lib bpf: Add missing BPF functions

Add more BPF map operations to libbpf. Also add bpf_obj_{pin,get}(). They
can be used on not only BPF maps but also BPF programs.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: He Kuang <hekuang@huawei.com>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-2-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/bpf/bpf.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/bpf.h |  7 +++++++
 2 files changed, 63 insertions(+)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 4212ed6..8143536 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -110,3 +110,59 @@ int bpf_map_update_elem(int fd, void *key, void *value,
 
 	return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
 }
+
+int bpf_map_lookup_elem(int fd, void *key, void *value)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.map_fd = fd;
+	attr.key = ptr_to_u64(key);
+	attr.value = ptr_to_u64(value);
+
+	return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
+}
+
+int bpf_map_delete_elem(int fd, void *key)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.map_fd = fd;
+	attr.key = ptr_to_u64(key);
+
+	return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
+}
+
+int bpf_map_get_next_key(int fd, void *key, void *next_key)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.map_fd = fd;
+	attr.key = ptr_to_u64(key);
+	attr.next_key = ptr_to_u64(next_key);
+
+	return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
+}
+
+int bpf_obj_pin(int fd, const char *pathname)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.pathname = ptr_to_u64((void *)pathname);
+	attr.bpf_fd = fd;
+
+	return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
+}
+
+int bpf_obj_get(const char *pathname)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.pathname = ptr_to_u64((void *)pathname);
+
+	return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
+}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index e8ba540..253c3db 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -35,4 +35,11 @@ int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
 
 int bpf_map_update_elem(int fd, void *key, void *value,
 			u64 flags);
+
+int bpf_map_lookup_elem(int fd, void *key, void *value);
+int bpf_map_delete_elem(int fd, void *key);
+int bpf_map_get_next_key(int fd, void *key, void *next_key);
+int bpf_obj_pin(int fd, const char *pathname);
+int bpf_obj_get(const char *pathname);
+
 #endif

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] tools lib bpf: Add private field for bpf_object
  2016-11-26  7:03 ` [PATCH v3 02/30] tools lib bpf: Add private field for bpf_object Wang Nan
  2016-11-26 17:11   ` Alexei Starovoitov
@ 2016-12-02 10:37   ` tip-bot for Wang Nan
  1 sibling, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-02 10:37 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, tglx, hekuang, mingo, joe, ast, linux-kernel, wangnan0,
	lizefan, acme

Commit-ID:  10931d2413478239bdceac5546cce85d7a497a4e
Gitweb:     http://git.kernel.org/tip/10931d2413478239bdceac5546cce85d7a497a4e
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:26 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 29 Nov 2016 12:09:41 -0300

tools lib bpf: Add private field for bpf_object

Similar to other classes defined in libbpf.h (map and program), allow
'object' class has its own private data.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: He Kuang <hekuang@huawei.com>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-3-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/bpf/libbpf.c | 23 +++++++++++++++++++++++
 tools/lib/bpf/libbpf.h |  5 +++++
 2 files changed, 28 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 96a2b2f..866d5cd 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -229,6 +229,10 @@ struct bpf_object {
 	 * all objects.
 	 */
 	struct list_head list;
+
+	void *priv;
+	bpf_object_clear_priv_t clear_priv;
+
 	char path[];
 };
 #define obj_elf_valid(o)	((o)->efile.elf)
@@ -1229,6 +1233,9 @@ void bpf_object__close(struct bpf_object *obj)
 	if (!obj)
 		return;
 
+	if (obj->clear_priv)
+		obj->clear_priv(obj, obj->priv);
+
 	bpf_object__elf_finish(obj);
 	bpf_object__unload(obj);
 
@@ -1282,6 +1289,22 @@ unsigned int bpf_object__kversion(struct bpf_object *obj)
 	return obj ? obj->kern_version : 0;
 }
 
+int bpf_object__set_priv(struct bpf_object *obj, void *priv,
+			 bpf_object_clear_priv_t clear_priv)
+{
+	if (obj->priv && obj->clear_priv)
+		obj->clear_priv(obj, obj->priv);
+
+	obj->priv = priv;
+	obj->clear_priv = clear_priv;
+	return 0;
+}
+
+void *bpf_object__priv(struct bpf_object *obj)
+{
+	return obj ? obj->priv : ERR_PTR(-EINVAL);
+}
+
 struct bpf_program *
 bpf_program__next(struct bpf_program *prev, struct bpf_object *obj)
 {
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index dd7a513..0c0b012 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -79,6 +79,11 @@ struct bpf_object *bpf_object__next(struct bpf_object *prev);
 	     (pos) != NULL;				\
 	     (pos) = (tmp), (tmp) = bpf_object__next(tmp))
 
+typedef void (*bpf_object_clear_priv_t)(struct bpf_object *, void *);
+int bpf_object__set_priv(struct bpf_object *obj, void *priv,
+			 bpf_object_clear_priv_t clear_priv);
+void *bpf_object__priv(struct bpf_object *prog);
+
 /* Accessors of bpf_program. */
 struct bpf_program;
 struct bpf_program *bpf_program__next(struct bpf_program *prog,

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] tools lib bpf: Retrive bpf_map through offset of bpf_map_def
  2016-11-26  7:03 ` [PATCH v3 03/30] tools lib bpf: Retrive bpf_map through offset of bpf_map_def Wang Nan
  2016-11-26 17:12   ` Alexei Starovoitov
@ 2016-12-02 10:38   ` tip-bot for Wang Nan
  1 sibling, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-02 10:38 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hekuang, linux-kernel, acme, mingo, jolsa, lizefan, wangnan0,
	tglx, hpa, ast, joe

Commit-ID:  5a6acad17d2e81765dd4c2fce7346a6f045eab25
Gitweb:     http://git.kernel.org/tip/5a6acad17d2e81765dd4c2fce7346a6f045eab25
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:27 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 29 Nov 2016 12:10:19 -0300

tools lib bpf: Retrive bpf_map through offset of bpf_map_def

Add a new API to libbpf, caller is able to get bpf_map through the
offset of bpf_map_def to 'maps' section.

The API will be used to help jitted perf hook code find fd of a map.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-4-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/bpf/libbpf.c | 12 ++++++++++++
 tools/lib/bpf/libbpf.h |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 866d5cd..2e97459 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1524,3 +1524,15 @@ bpf_object__find_map_by_name(struct bpf_object *obj, const char *name)
 	}
 	return NULL;
 }
+
+struct bpf_map *
+bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset)
+{
+	int i;
+
+	for (i = 0; i < obj->nr_maps; i++) {
+		if (obj->maps[i].offset == offset)
+			return &obj->maps[i];
+	}
+	return ERR_PTR(-ENOENT);
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 0c0b012..a5a8b86 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -24,6 +24,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <linux/err.h>
+#include <sys/types.h>  // for size_t
 
 enum libbpf_errno {
 	__LIBBPF_ERRNO__START = 4000,
@@ -200,6 +201,13 @@ struct bpf_map;
 struct bpf_map *
 bpf_object__find_map_by_name(struct bpf_object *obj, const char *name);
 
+/*
+ * Get bpf_map through the offset of corresponding struct bpf_map_def
+ * in the bpf object file.
+ */
+struct bpf_map *
+bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset);
+
 struct bpf_map *
 bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
 #define bpf_map__for_each(pos, obj)		\

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] perf tools: Introduce perf hooks
  2016-11-26  7:03 ` [PATCH v3 04/30] perf tools: Introduce perf hooks Wang Nan
@ 2016-12-02 10:38   ` tip-bot for Wang Nan
  0 siblings, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-02 10:38 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, ast, lizefan, tglx, hpa, jolsa, acme, wangnan0, joe,
	hekuang, linux-kernel

Commit-ID:  a074865e60edd762b99ec5dacec69b406f702e66
Gitweb:     http://git.kernel.org/tip/a074865e60edd762b99ec5dacec69b406f702e66
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:28 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 29 Nov 2016 12:13:27 -0300

perf tools: Introduce perf hooks

Perf hooks allow hooking user code at perf events. They can be used for
manipulation of BPF maps, taking snapshot and reporting results. In this
patch two perf hook points are introduced: record_start and record_end.

To avoid buggy user actions, a SIGSEGV signal handler is introduced into
'perf record'. It turns off perf hook if it causes a segfault and report
an error to help debugging.

A test case for perf hook is introduced.

Test result:
  $ ./buildperf/perf test -v hook
  50: Test perf hooks                                          :
  --- start ---
  test child forked, pid 10311
  SIGSEGV is observed as expected, try to recover.
  Fatal error (SEGFAULT) in perf hook 'test'
  test child finished with 0
  ---- end ----
  Test perf hooks: Ok

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-5-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c       | 11 +++++
 tools/perf/tests/Build            |  1 +
 tools/perf/tests/builtin-test.c   |  4 ++
 tools/perf/tests/perf-hooks.c     | 44 ++++++++++++++++++++
 tools/perf/tests/tests.h          |  1 +
 tools/perf/util/Build             |  2 +
 tools/perf/util/perf-hooks-list.h |  3 ++
 tools/perf/util/perf-hooks.c      | 84 +++++++++++++++++++++++++++++++++++++++
 tools/perf/util/perf-hooks.h      | 37 +++++++++++++++++
 9 files changed, 187 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 67d2a90..fa26865 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -37,6 +37,7 @@
 #include "util/llvm-utils.h"
 #include "util/bpf-loader.h"
 #include "util/trigger.h"
+#include "util/perf-hooks.h"
 #include "asm/bug.h"
 
 #include <unistd.h>
@@ -206,6 +207,12 @@ static void sig_handler(int sig)
 	done = 1;
 }
 
+static void sigsegv_handler(int sig)
+{
+	perf_hooks__recover();
+	sighandler_dump_stack(sig);
+}
+
 static void record__sig_exit(void)
 {
 	if (signr == -1)
@@ -833,6 +840,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 	signal(SIGCHLD, sig_handler);
 	signal(SIGINT, sig_handler);
 	signal(SIGTERM, sig_handler);
+	signal(SIGSEGV, sigsegv_handler);
 
 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
 		signal(SIGUSR2, snapshot_sig_handler);
@@ -970,6 +978,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 
 	trigger_ready(&auxtrace_snapshot_trigger);
 	trigger_ready(&switch_output_trigger);
+	perf_hooks__invoke_record_start();
 	for (;;) {
 		unsigned long long hits = rec->samples;
 
@@ -1114,6 +1123,8 @@ out_child:
 		}
 	}
 
+	perf_hooks__invoke_record_end();
+
 	if (!err && !quiet) {
 		char samples[128];
 		const char *postfix = rec->timestamp_filename ?
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 8a4ce49..af3ec94 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -42,6 +42,7 @@ perf-y += backward-ring-buffer.o
 perf-y += sdt.o
 perf-y += is_printable_array.o
 perf-y += bitmap.o
+perf-y += perf-hooks.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
 	$(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 778668a..dab83f7 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -230,6 +230,10 @@ static struct test generic_tests[] = {
 		.func = test__bitmap_print,
 	},
 	{
+		.desc = "Test perf hooks",
+		.func = test__perf_hooks,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/perf-hooks.c b/tools/perf/tests/perf-hooks.c
new file mode 100644
index 0000000..9338cb2
--- /dev/null
+++ b/tools/perf/tests/perf-hooks.c
@@ -0,0 +1,44 @@
+#include <signal.h>
+#include <stdlib.h>
+
+#include "tests.h"
+#include "debug.h"
+#include "util.h"
+#include "perf-hooks.h"
+
+static void sigsegv_handler(int sig __maybe_unused)
+{
+	pr_debug("SIGSEGV is observed as expected, try to recover.\n");
+	perf_hooks__recover();
+	signal(SIGSEGV, SIG_DFL);
+	raise(SIGSEGV);
+	exit(-1);
+}
+
+static int hook_flags;
+
+static void the_hook(void)
+{
+	int *p = NULL;
+
+	hook_flags = 1234;
+
+	/* Generate a segfault, test perf_hooks__recover */
+	*p = 0;
+}
+
+int test__perf_hooks(int subtest __maybe_unused)
+{
+	signal(SIGSEGV, sigsegv_handler);
+	perf_hooks__set_hook("test", the_hook);
+	perf_hooks__invoke_test();
+
+	/* hook is triggered? */
+	if (hook_flags != 1234)
+		return TEST_FAIL;
+
+	/* the buggy hook is removed? */
+	if (perf_hooks__get_hook("test"))
+		return TEST_FAIL;
+	return TEST_OK;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 7c196c5..3a1f98f 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -91,6 +91,7 @@ int test__cpu_map_print(int subtest);
 int test__sdt_event(int subtest);
 int test__is_printable_array(int subtest);
 int test__bitmap_print(int subtest);
+int test__perf_hooks(int subtest);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 1dc67ef..b2a47aa 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -123,6 +123,8 @@ libperf-$(CONFIG_LIBELF) += genelf.o
 libperf-$(CONFIG_DWARF) += genelf_debug.o
 endif
 
+libperf-y += perf-hooks.o
+
 CFLAGS_config.o   += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
 # avoid compiler warnings in 32-bit mode
 CFLAGS_genelf_debug.o  += -Wno-packed
diff --git a/tools/perf/util/perf-hooks-list.h b/tools/perf/util/perf-hooks-list.h
new file mode 100644
index 0000000..2867c07
--- /dev/null
+++ b/tools/perf/util/perf-hooks-list.h
@@ -0,0 +1,3 @@
+PERF_HOOK(record_start)
+PERF_HOOK(record_end)
+PERF_HOOK(test)
diff --git a/tools/perf/util/perf-hooks.c b/tools/perf/util/perf-hooks.c
new file mode 100644
index 0000000..4ce88e3
--- /dev/null
+++ b/tools/perf/util/perf-hooks.c
@@ -0,0 +1,84 @@
+/*
+ * perf_hooks.c
+ *
+ * Copyright (C) 2016 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2016 Huawei Inc.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <linux/err.h>
+#include "util/util.h"
+#include "util/debug.h"
+#include "util/perf-hooks.h"
+
+static sigjmp_buf jmpbuf;
+static const struct perf_hook_desc *current_perf_hook;
+
+void perf_hooks__invoke(const struct perf_hook_desc *desc)
+{
+	if (!(desc && desc->p_hook_func && *desc->p_hook_func))
+		return;
+
+	if (sigsetjmp(jmpbuf, 1)) {
+		pr_warning("Fatal error (SEGFAULT) in perf hook '%s'\n",
+			   desc->hook_name);
+		*(current_perf_hook->p_hook_func) = NULL;
+	} else {
+		current_perf_hook = desc;
+		(**desc->p_hook_func)();
+	}
+	current_perf_hook = NULL;
+}
+
+void perf_hooks__recover(void)
+{
+	if (current_perf_hook)
+		siglongjmp(jmpbuf, 1);
+}
+
+#define PERF_HOOK(name)					\
+perf_hook_func_t __perf_hook_func_##name = NULL;	\
+struct perf_hook_desc __perf_hook_desc_##name =		\
+	{.hook_name = #name, .p_hook_func = &__perf_hook_func_##name};
+#include "perf-hooks-list.h"
+#undef PERF_HOOK
+
+#define PERF_HOOK(name)		\
+	&__perf_hook_desc_##name,
+
+static struct perf_hook_desc *perf_hooks[] = {
+#include "perf-hooks-list.h"
+};
+#undef PERF_HOOK
+
+int perf_hooks__set_hook(const char *hook_name,
+			 perf_hook_func_t hook_func)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(perf_hooks); i++) {
+		if (strcmp(hook_name, perf_hooks[i]->hook_name) != 0)
+			continue;
+
+		if (*(perf_hooks[i]->p_hook_func))
+			pr_warning("Overwrite existing hook: %s\n", hook_name);
+		*(perf_hooks[i]->p_hook_func) = hook_func;
+		return 0;
+	}
+	return -ENOENT;
+}
+
+perf_hook_func_t perf_hooks__get_hook(const char *hook_name)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(perf_hooks); i++) {
+		if (strcmp(hook_name, perf_hooks[i]->hook_name) != 0)
+			continue;
+
+		return *(perf_hooks[i]->p_hook_func);
+	}
+	return ERR_PTR(-ENOENT);
+}
diff --git a/tools/perf/util/perf-hooks.h b/tools/perf/util/perf-hooks.h
new file mode 100644
index 0000000..1d482b2
--- /dev/null
+++ b/tools/perf/util/perf-hooks.h
@@ -0,0 +1,37 @@
+#ifndef PERF_UTIL_PERF_HOOKS_H
+#define PERF_UTIL_PERF_HOOKS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*perf_hook_func_t)(void);
+struct perf_hook_desc {
+	const char * const hook_name;
+	perf_hook_func_t * const p_hook_func;
+};
+
+extern void perf_hooks__invoke(const struct perf_hook_desc *);
+extern void perf_hooks__recover(void);
+
+#define PERF_HOOK(name)					\
+extern struct perf_hook_desc __perf_hook_desc_##name;	\
+static inline void perf_hooks__invoke_##name(void)	\
+{ 							\
+	perf_hooks__invoke(&__perf_hook_desc_##name);	\
+}
+
+#include "perf-hooks-list.h"
+#undef PERF_HOOK
+
+extern int
+perf_hooks__set_hook(const char *hook_name,
+		     perf_hook_func_t hook_func);
+
+extern perf_hook_func_t
+perf_hooks__get_hook(const char *hook_name);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-11-26  7:03 ` [PATCH v3 10/30] perf clang: Add builtin clang support ant test case Wang Nan
  2016-11-26 17:17   ` Alexei Starovoitov
@ 2016-12-02 15:44   ` Arnaldo Carvalho de Melo
  2016-12-05  2:36     ` Wangnan (F)
  2016-12-05 16:51     ` Alexei Starovoitov
  2016-12-06  8:23   ` [tip:perf/core] " tip-bot for Wang Nan
  2 siblings, 2 replies; 73+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-12-02 15:44 UTC (permalink / raw)
  To: Wang Nan
  Cc: ast, lizefan, hekuang, Ingo Molnar, linux-kernel, pi3orama, joe,
	Jiri Olsa, acme

Em Sat, Nov 26, 2016 at 07:03:34AM +0000, Wang Nan escreveu:
> Add basic clang support in clang.cpp and test__clang() testcase. The
> first testcase checks if builtin clang is able to generate LLVM IR.
> 
> tests/clang.c is a proxy. Real testcase resides in
> utils/c++/clang-test.cpp in c++ and exports C interface to perf test
> subsystem.
> 
> Test result:
> 
>    $ perf test -v clang
>    51: Test builtin clang support                               :
>    51.1: Test builtin clang compile C source to IR              :
>    --- start ---
>    test child forked, pid 13215
>    test child finished with 0
>    ---- end ----
>    Test builtin clang support subtest 0: Ok

While testing this I noticed that the perf binary got huge, can't this
be done in some other way, i.e. using dynamic library?

[root@jouet ~]# size /tmp/perf
   text	   data	    bss	    dec	    hex	filename
75333688	1421584	23962176	100717448	600d388 /tmp/perf
[root@jouet ~]#

I've built it with this:

  make LIBCLANGLLVM=1 O=/tmp/build/perf -C tools/perf install-bin

the resulting binary:

[acme@jouet linux]$ 
[acme@jouet linux]$ ls -la ~/bin/perf
-rwxr-xr-x. 2 acme acme 131689136 Dec  2 12:31 /home/acme/bin/perf
[acme@jouet linux]$ ls -lah ~/bin/perf
-rwxr-xr-x. 2 acme acme 126M Dec  2 12:31 /home/acme/bin/perf
[acme@jouet linux]$

Huge, after stripping it:

[acme@jouet linux]$ ls -la /tmp/perf
-rwxr-xr-x. 1 root root 76759056 Dec  2 12:33 /tmp/perf
[acme@jouet linux]$ ls -lah /tmp/perf
-rwxr-xr-x. 1 root root 74M Dec  2 12:33 /tmp/perf
[acme@jouet linux]$

Still huge :-\

Ok, this needs explicitely enabling, but then, for distros, if we want
this feature to be enabled...

I think we should try to help distributions to ship a basic perf binary
in a base package that doesn't brings many libraries, like was done for
the gtk UI, and also we should start providing RPM specfiles and debian
(and others, hopefully contributed by other people with interest in
other distros), to help in getting a sane package split, i.e. want
llvm/bpf? install the 'perf-ebpf' rpm/deb/whatever package and incur in
these costs.

But being a n00b on llvm/clang libraries, etc, my question goes back to:
can we have this using a libllvm.so or libclang.so dynamic libraries?

See this, out of hand :-\ Tell me I'm doing something wrong :-)

[acme@jouet linux]$ cat /etc/fedora-release 
Fedora release 25 (Twenty Five)
[acme@jouet linux]$ rpm -qa | egrep llvm\|clang
llvm-libs-3.8.0-1.fc25.x86_64
[acme@jouet linux]$

[acme@jouet linux]$ nm ~/bin/perf | grep -i clang | wc -l
204757

[acme@jouet linux]$ nm ~/bin/perf | grep -i llvm | wc -l
234036

[acme@jouet linux]$ nm ~/bin/perf | grep -i clang | tail
00000000011741ba t
_ZZZN5clang7CodeGen15CodeGenFunction20EmitOMPTaskDirectiveERKNS_16OMPTaskDirectiveEENKUlRS1_E_clES5_ENKUlvE_clEv
0000000001169fee t
_ZZZN5clang7CodeGen15CodeGenFunction25EmitOMPFirstprivateClauseERKNS_22OMPExecutableDirectiveERNS1_15OMPPrivateScopeEENKUlvE_clEvENKUlNS0_7AddressES8_E_clES8_S8_
00000000038b83e0 r
_ZZZN5clang9ASTReader24FindExternalLexicalDeclsEPKNS_11DeclContextEN4llvm12function_refIFbNS_4Decl4KindEEEERNS4_15SmallVectorImplIPS6_EEENKUlPNS_13serialization10ModuleFileENS4_8ArrayRefINS4_7support6detail31packed_endian_specific_integralIjLNSI_10endiannessE2ELm1EEEEEE_clESG_SN_E19__PRETTY_FUNCTION__
0000000003934140 r
_ZZZN5clang9ASTWriter12WriteASTCoreERNS_4SemaEN4llvm9StringRefERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPNS_6ModuleEENKUljbE0_clEjbE19__PRETTY_FUNCTION__
00000000039319e0 r
_ZZZN5clang9ASTWriter12WriteASTCoreERNS_4SemaEN4llvm9StringRefERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPNS_6ModuleEENKUlPNS_4DeclENS_13serialization17PredefinedDeclIDsEE_clESG_SI_E19__PRETTY_FUNCTION__
000000000393b700 r
_ZZZN5clang9ASTWriter17GetOrCreateTypeIDENS_8QualTypeEENKUlS1_E_clES1_E19__PRETTY_FUNCTION__
000000000393b880 r
_ZZZNK5clang9ASTWriter9getTypeIDENS_8QualTypeEENKUlS1_E_clES1_E19__PRETTY_FUNCTION__
0000000002176480 t
_ZZZZN12_GLOBAL__N_19ASTDumper11dumpLookupsEPKN5clang11DeclContextEbENKUlvE_clEvENKUlvE_clEvENKUlvE_clEv
000000000144ef0a t
_ZZZZN5clang7CodeGen15CGOpenMPRuntime13emitReductionERNS0_15CodeGenFunctionENS_14SourceLocationEN4llvm8ArrayRefIPKNS_4ExprEEESA_SA_SA_bbENKUlS3_S9_S9_S9_E1_clES3_S9_S9_S9_ENKUlNS0_6RValueEE_clESC_ENKUlvE_clEv
000000000217640c t
_ZZZZZN12_GLOBAL__N_19ASTDumper11dumpLookupsEPKN5clang11DeclContextEbENKUlvE_clEvENKUlvE_clEvENKUlvE_clEvENKUlPNS1_4DeclEE_clES9_
[acme@jouet linux]$

Thanks,

- Arnaldo

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-12-02 15:44   ` Arnaldo Carvalho de Melo
@ 2016-12-05  2:36     ` Wangnan (F)
  2016-12-05  4:41       ` Wangnan (F)
  2016-12-05 16:51     ` Alexei Starovoitov
  1 sibling, 1 reply; 73+ messages in thread
From: Wangnan (F) @ 2016-12-05  2:36 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, ast
  Cc: lizefan, hekuang, Ingo Molnar, linux-kernel, pi3orama, joe,
	Jiri Olsa, acme



On 2016/12/2 23:44, Arnaldo Carvalho de Melo wrote:
> Em Sat, Nov 26, 2016 at 07:03:34AM +0000, Wang Nan escreveu:
>> Add basic clang support in clang.cpp and test__clang() testcase. The
>> first testcase checks if builtin clang is able to generate LLVM IR.
>>
>> tests/clang.c is a proxy. Real testcase resides in
>> utils/c++/clang-test.cpp in c++ and exports C interface to perf test
>> subsystem.
>>
>> Test result:
>>
>>     $ perf test -v clang
>>     51: Test builtin clang support                               :
>>     51.1: Test builtin clang compile C source to IR              :
>>     --- start ---
>>     test child forked, pid 13215
>>     test child finished with 0
>>     ---- end ----
>>     Test builtin clang support subtest 0: Ok
> While testing this I noticed that the perf binary got huge, can't this
> be done in some other way, i.e. using dynamic library?

I intentionally use statically linking because it is good for
smartphone: we can simply 'adb push' a statically linked perf
to Android.

The resulting ELF executable would be even larger if LLVM is
built with default setting.

In my setting the resuling 'perf' is less than 60MB:

  $ ls -s  ~/perf -h
  58M /home/wn/perf

  $ size  ~/perf
    text       data        bss        dec        hex    filename
  56931273    2950808    24108632    83990713    50198b9 /home/wn/perf

It is reasonable for me.

I think using dynamic clang and llvm libraries is possible but I
never tried it before. It depend on LLVM compiling. I think if
distro provides shared libraries then perf can utilize them
automatically. Let me check it today.

About the file size, I discussed with Alexei, he taught me a lot
on it. Maybe he or his ioVisor ex-colleagues can provide some
new idea?

Thank you.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-12-05  2:36     ` Wangnan (F)
@ 2016-12-05  4:41       ` Wangnan (F)
  2017-01-17 13:38         ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 73+ messages in thread
From: Wangnan (F) @ 2016-12-05  4:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, ast
  Cc: lizefan, hekuang, Ingo Molnar, linux-kernel, pi3orama, joe,
	Jiri Olsa, acme



On 2016/12/5 10:36, Wangnan (F) wrote:
>
>
> On 2016/12/2 23:44, Arnaldo Carvalho de Melo wrote:
>> Em Sat, Nov 26, 2016 at 07:03:34AM +0000, Wang Nan escreveu:
>>> Add basic clang support in clang.cpp and test__clang() testcase. The
>>> first testcase checks if builtin clang is able to generate LLVM IR.
>>>
>>> tests/clang.c is a proxy. Real testcase resides in
>>> utils/c++/clang-test.cpp in c++ and exports C interface to perf test
>>> subsystem.
>>>
>>> Test result:
>>>
>>>     $ perf test -v clang
>>>     51: Test builtin clang support                               :
>>>     51.1: Test builtin clang compile C source to IR              :
>>>     --- start ---
>>>     test child forked, pid 13215
>>>     test child finished with 0
>>>     ---- end ----
>>>     Test builtin clang support subtest 0: Ok
>> While testing this I noticed that the perf binary got huge, can't this
>> be done in some other way, i.e. using dynamic library?
>
> I intentionally use statically linking because it is good for
> smartphone: we can simply 'adb push' a statically linked perf
> to Android.
>
> The resulting ELF executable would be even larger if LLVM is
> built with default setting.
>
> In my setting the resuling 'perf' is less than 60MB:
>
>  $ ls -s  ~/perf -h
>  58M /home/wn/perf
>
>  $ size  ~/perf
>    text       data        bss        dec        hex    filename
>  56931273    2950808    24108632    83990713    50198b9 /home/wn/perf
>
> It is reasonable for me.
>
> I think using dynamic clang and llvm libraries is possible but I
> never tried it before. It depend on LLVM compiling. I think if
> distro provides shared libraries then perf can utilize them
> automatically. Let me check it today.
>

Good news: it works.

To enable llvm and clang dynamic libraries, we need to build llvm and 
clang with
cmake option -DBUILD_SHARED_LIBS=ON. Then apply a trivial patch to perf:

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index dfb20dd..e3054f3 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -346,7 +346,7 @@ LIBS = -Wl,--whole-archive $(PERFLIBS) 
-Wl,--no-whole-archive -Wl,--start-group

  ifeq ($(USE_CLANG), 1)
    CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit 
Sema Analysis Parse Serialization
-  LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell 
$(LLVM_CONFIG) --libdir)/libclang$(l).a))
+  LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell 
$(LLVM_CONFIG) --libdir)/libclang$(l).so))
    LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group
  endif

(replace '.a' to '.so')

Resuling perf executable:

$ ls -s -h ~/perf
26M /home/wn/perf

$ size ~/perf
    text       data        bss        dec        hex    filename
4274339     755032    23959984    28989355    1ba57ab /home/wn/perf

$ strip ~/perf
$ ls -s -h
4.9M /home/wn/perf

$ ldd ~/perf | grep 'LLVM\|clang'
     libclangBasic.so => /tmp/oxygen_root/usr/lib64/libclangBasic.so 
(0x00007f24da49f000)
     libclangCodeGen.so => /tmp/oxygen_root/usr/lib64/libclangCodeGen.so 
(0x00007f24d9f72000)
     libclangFrontend.so => 
/tmp/oxygen_root/usr/lib64/libclangFrontend.so (0x00007f24d9c64000)
     libclangTooling.so => /tmp/oxygen_root/usr/lib64/libclangTooling.so 
(0x00007f24d9a01000)
     libLLVMBPFCodeGen.so => 
/tmp/oxygen_root/usr/lib64/libLLVMBPFCodeGen.so (0x00007f24d97e2000)
     libLLVMBPFDesc.so => /tmp/oxygen_root/usr/lib64/libLLVMBPFDesc.so 
(0x00007f24d95da000)
     ....

As I said, if distro provides dynamic libraries then everything would be 
fine.

If you are okay with the above conclusion, in next version I'll use 
'-lclangBasic'
style linking options so it works for both dynamic and static 
LLVM/clang, then let's
wait for distro's action.

Thank you.

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-12-02 15:44   ` Arnaldo Carvalho de Melo
  2016-12-05  2:36     ` Wangnan (F)
@ 2016-12-05 16:51     ` Alexei Starovoitov
  2016-12-05 21:02       ` Arnaldo Carvalho de Melo
  2016-12-06 19:19       ` Arnaldo Carvalho de Melo
  1 sibling, 2 replies; 73+ messages in thread
From: Alexei Starovoitov @ 2016-12-05 16:51 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Wang Nan, ast, lizefan, hekuang, Ingo Molnar, linux-kernel,
	pi3orama, joe, Jiri Olsa, acme

On Fri, Dec 02, 2016 at 01:44:40PM -0200, Arnaldo Carvalho de Melo wrote:
> Em Sat, Nov 26, 2016 at 07:03:34AM +0000, Wang Nan escreveu:
> > Add basic clang support in clang.cpp and test__clang() testcase. The
> > first testcase checks if builtin clang is able to generate LLVM IR.
> > 
> > tests/clang.c is a proxy. Real testcase resides in
> > utils/c++/clang-test.cpp in c++ and exports C interface to perf test
> > subsystem.
> > 
> > Test result:
> > 
> >    $ perf test -v clang
> >    51: Test builtin clang support                               :
> >    51.1: Test builtin clang compile C source to IR              :
> >    --- start ---
> >    test child forked, pid 13215
> >    test child finished with 0
> >    ---- end ----
> >    Test builtin clang support subtest 0: Ok
> 
> While testing this I noticed that the perf binary got huge, can't this
> be done in some other way, i.e. using dynamic library?
> 
> [root@jouet ~]# size /tmp/perf
>    text	   data	    bss	    dec	    hex	filename
> 75333688	1421584	23962176	100717448	600d388 /tmp/perf
> [root@jouet ~]#
> 
> I've built it with this:
> 
>   make LIBCLANGLLVM=1 O=/tmp/build/perf -C tools/perf install-bin
> 
> the resulting binary:
> 
> [acme@jouet linux]$ 
> [acme@jouet linux]$ ls -la ~/bin/perf
> -rwxr-xr-x. 2 acme acme 131689136 Dec  2 12:31 /home/acme/bin/perf
> [acme@jouet linux]$ ls -lah ~/bin/perf
> -rwxr-xr-x. 2 acme acme 126M Dec  2 12:31 /home/acme/bin/perf
> [acme@jouet linux]$
> 
> Huge, after stripping it:
> 
> [acme@jouet linux]$ ls -la /tmp/perf
> -rwxr-xr-x. 1 root root 76759056 Dec  2 12:33 /tmp/perf
> [acme@jouet linux]$ ls -lah /tmp/perf
> -rwxr-xr-x. 1 root root 74M Dec  2 12:33 /tmp/perf
> [acme@jouet linux]$
> 
> Still huge :-\

yeah. it's kinda high. I'm guessing rpm llvm libs are in debug mode.
Try llvm-config --build-mode --assertion-mode
it should be Release OFF

> But being a n00b on llvm/clang libraries, etc, my question goes back to:
> can we have this using a libllvm.so or libclang.so dynamic libraries?

that can also work. The reason we build iovisor/bcc into single binary
is to ease operational headache.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-12-05 16:51     ` Alexei Starovoitov
@ 2016-12-05 21:02       ` Arnaldo Carvalho de Melo
  2016-12-05 21:48         ` Arnaldo Carvalho de Melo
  2016-12-06 19:19       ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 73+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-12-05 21:02 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Wang Nan, ast, lizefan, hekuang, Ingo Molnar, linux-kernel,
	pi3orama, joe, Jiri Olsa, acme

Em Mon, Dec 05, 2016 at 08:51:01AM -0800, Alexei Starovoitov escreveu:
> On Fri, Dec 02, 2016 at 01:44:40PM -0200, Arnaldo Carvalho de Melo wrote:
> > Em Sat, Nov 26, 2016 at 07:03:34AM +0000, Wang Nan escreveu:
> > > Add basic clang support in clang.cpp and test__clang() testcase. The
> > > first testcase checks if builtin clang is able to generate LLVM IR.
> > > 
> > > tests/clang.c is a proxy. Real testcase resides in
> > > utils/c++/clang-test.cpp in c++ and exports C interface to perf test
> > > subsystem.
> > > 
> > > Test result:
> > > 
> > >    $ perf test -v clang
> > >    51: Test builtin clang support                               :
> > >    51.1: Test builtin clang compile C source to IR              :
> > >    --- start ---
> > >    test child forked, pid 13215
> > >    test child finished with 0
> > >    ---- end ----
> > >    Test builtin clang support subtest 0: Ok
> > 
> > While testing this I noticed that the perf binary got huge, can't this
> > be done in some other way, i.e. using dynamic library?
> > 
> > [root@jouet ~]# size /tmp/perf
> >    text	   data	    bss	    dec	    hex	filename
> > 75333688	1421584	23962176	100717448	600d388 /tmp/perf
> > [root@jouet ~]#
> > 
> > I've built it with this:
> > 
> >   make LIBCLANGLLVM=1 O=/tmp/build/perf -C tools/perf install-bin
> > 
> > the resulting binary:
> > 
> > [acme@jouet linux]$ 
> > [acme@jouet linux]$ ls -la ~/bin/perf
> > -rwxr-xr-x. 2 acme acme 131689136 Dec  2 12:31 /home/acme/bin/perf
> > [acme@jouet linux]$ ls -lah ~/bin/perf
> > -rwxr-xr-x. 2 acme acme 126M Dec  2 12:31 /home/acme/bin/perf
> > [acme@jouet linux]$
> > 
> > Huge, after stripping it:
> > 
> > [acme@jouet linux]$ ls -la /tmp/perf
> > -rwxr-xr-x. 1 root root 76759056 Dec  2 12:33 /tmp/perf
> > [acme@jouet linux]$ ls -lah /tmp/perf
> > -rwxr-xr-x. 1 root root 74M Dec  2 12:33 /tmp/perf
> > [acme@jouet linux]$
> > 
> > Still huge :-\
> 
> yeah. it's kinda high. I'm guessing rpm llvm libs are in debug mode.
> Try llvm-config --build-mode --assertion-mode
> it should be Release OFF

Probably this was with 3.9 and built from git, quite a while ago, now I
removed it from /usr/local/ and installed what is in f25, but I fear it
will be insufficient, does 3.8 cuts it for what we're testing? Humm, it
looks like it will:

[root@jouet ~]# llc --version
LLVM (http://llvm.org/):
  LLVM version 3.8.0
  Optimized build.
  Built Mar 10 2016 (01:41:45).
  Default target: x86_64-unknown-linux-gnu
  Host CPU: broadwell

  Registered Targets:
    aarch64    - AArch64 (little endian)
    aarch64_be - AArch64 (big endian)
    amdgcn     - AMD GCN GPUs
    arm        - ARM
    arm64      - ARM64 (little endian)
    armeb      - ARM (big endian)
    bpf        - BPF (host endian)
    bpfeb      - BPF (big endian)
    bpfel      - BPF (little endian)
    cpp        - C++ backend
    nvptx      - NVIDIA PTX 32-bit
    nvptx64    - NVIDIA PTX 64-bit
    ppc32      - PowerPC 32
    ppc64      - PowerPC 64
    ppc64le    - PowerPC 64 LE
    r600       - AMD GPUs HD2XXX-HD6XXX
    systemz    - SystemZ
    thumb      - Thumb
    thumbeb    - Thumb (big endian)
    x86        - 32-bit X86: Pentium-Pro and above
    x86-64     - 64-bit X86: EM64T and AMD64
[root@jouet ~]# 

But I'm now running the container based tests to send a pull req, will
check later, after that.

- Arnaldo
 
> > But being a n00b on llvm/clang libraries, etc, my question goes back to:
> > can we have this using a libllvm.so or libclang.so dynamic libraries?
> 
> that can also work. The reason we build iovisor/bcc into single binary
> is to ease operational headache.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-12-05 21:02       ` Arnaldo Carvalho de Melo
@ 2016-12-05 21:48         ` Arnaldo Carvalho de Melo
  2016-12-06  2:07           ` Wangnan (F)
  0 siblings, 1 reply; 73+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-12-05 21:48 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Wang Nan, ast, lizefan, hekuang, Ingo Molnar, linux-kernel,
	pi3orama, joe, Jiri Olsa, acme

Em Mon, Dec 05, 2016 at 07:02:48PM -0200, Arnaldo Carvalho de Melo escreveu:
> Em Mon, Dec 05, 2016 at 08:51:01AM -0800, Alexei Starovoitov escreveu:
> > yeah. it's kinda high. I'm guessing rpm llvm libs are in debug mode.
> > Try llvm-config --build-mode --assertion-mode
> > it should be Release OFF
> 
> Probably this was with 3.9 and built from git, quite a while ago, now I
> removed it from /usr/local/ and installed what is in f25, but I fear it
> will be insufficient, does 3.8 cuts it for what we're testing? Humm, it
> looks like it will:
> 
> [root@jouet ~]# llc --version
> LLVM (http://llvm.org/):
>   LLVM version 3.8.0
> 
> But I'm now running the container based tests to send a pull req, will
> check later, after that.

Not really, Wang, we need to update that feature detection test to state what
is the minimum required LLVM/clang version, one that has those functions,
which, unfortunately, isn't the one in the latest fedora, fedora 25:

[acme@jouet linux]$ rpm -q llvm-devel clang-devel
llvm-devel-3.8.0-1.fc25.x86_64
clang-devel-3.8.0-2.fc25.x86_64
[acme@jouet linux]$ 


  LINK     /tmp/build/perf/libperf-gtk.so
  INSTALL  GTK UI
/tmp/build/perf/libperf.a(libperf-in.o): In function `perf::createCompilerInvocation(llvm::SmallVector<char const*, 16u>, llvm::StringRef&, clang::DiagnosticsEngine&)':
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:56: undefined reference to `clang::tooling::newInvocation(clang::DiagnosticsEngine*, llvm::SmallVector<char const*, 16u> const&)'
/tmp/build/perf/libperf.a(libperf-in.o): In function `perf::getModuleFromSource(llvm::SmallVector<char const*, 16u>, llvm::StringRef, llvm::IntrusiveRefCntPtr<clang::vfs::FileSystem>)':
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:68: undefined reference to `clang::CompilerInstance::CompilerInstance(std::shared_ptr<clang::PCHContainerOperations>, bool)'
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:69: undefined reference to `clang::CompilerInstance::createDiagnostics(clang::DiagnosticConsumer*, bool)'
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:76: undefined reference to `clang::CompilerInstance::setInvocation(clang::CompilerInvocation*)'
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:78: undefined reference to `clang::EmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext*)'
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:79: undefined reference to `clang::CompilerInstance::ExecuteAction(clang::FrontendAction&)'
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:82: undefined reference to `clang::CodeGenAction::takeModule()'
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:68: undefined reference to `clang::CompilerInstance::~CompilerInstance()'
/tmp/build/perf/libperf.a(libperf-in.o): In function `perf::getModuleFromSource(llvm::SmallVector<char const*, 16u>, llvm::StringRef, llvm::StringRef)':
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:92: undefined reference to `clang::vfs::getRealFileSystem()'
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:92: undefined reference to `clang::vfs::OverlayFileSystem::OverlayFileSystem(llvm::IntrusiveRefCntPtr<clang::vfs::FileSystem>)'
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:94: undefined reference to `clang::vfs::InMemoryFileSystem::InMemoryFileSystem(bool)'
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:100: undefined reference to `clang::vfs::OverlayFileSystem::pushOverlay(llvm::IntrusiveRefCntPtr<clang::vfs::FileSystem>)'
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:101: undefined reference to `clang::vfs::InMemoryFileSystem::addFile(llvm::Twine const&, long, std::unique_ptr<llvm::MemoryBuffer, std::default_delete<llvm::MemoryBuffer> >)'
/tmp/build/perf/libperf.a(libperf-in.o): In function `perf::getModuleFromSource(llvm::SmallVector<char const*, 16u>, llvm::StringRef)':
/home/acme/git/linux/tools/perf/util/c++/clang.cpp:109: undefined reference to `clang::vfs::getRealFileSystem()'
/tmp/build/perf/libperf.a(libperf-in.o): In function `clang::CompilerInvocation::~CompilerInvocation()':
/usr/include/clang/Frontend/CompilerInvocation.h:102: undefined reference to `clang::CompilerInvocationBase::~CompilerInvocationBase()'
/tmp/build/perf/libperf.a(libperf-in.o): In function `void __gnu_cxx::new_allocator<clang::PCHContainerOperations>::construct<clang::PCHContainerOperations>(clang::PCHContainerOperations*)':
/usr/include/c++/6.2.1/ext/new_allocator.h:120: undefined reference to `clang::PCHContainerOperations::PCHContainerOperations()'
collect2: error: ld returned 1 exit status
Makefile.perf:491: recipe for target '/tmp/build/perf/perf' failed
make[1]: *** [/tmp/build/perf/perf] Error 1
Makefile:108: recipe for target 'install-bin' failed
make: *** [install-bin] Error 2
make: Leaving directory '/home/acme/git/linux/tools/perf'
[acme@jouet linux]$

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-12-05 21:48         ` Arnaldo Carvalho de Melo
@ 2016-12-06  2:07           ` Wangnan (F)
  2016-12-06 13:43             ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 73+ messages in thread
From: Wangnan (F) @ 2016-12-06  2:07 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Alexei Starovoitov
  Cc: ast, lizefan, hekuang, Ingo Molnar, linux-kernel, pi3orama, joe,
	Jiri Olsa, acme



On 2016/12/6 5:48, Arnaldo Carvalho de Melo wrote:
> Em Mon, Dec 05, 2016 at 07:02:48PM -0200, Arnaldo Carvalho de Melo escreveu:
>> Em Mon, Dec 05, 2016 at 08:51:01AM -0800, Alexei Starovoitov escreveu:
>>> yeah. it's kinda high. I'm guessing rpm llvm libs are in debug mode.
>>> Try llvm-config --build-mode --assertion-mode
>>> it should be Release OFF
>> Probably this was with 3.9 and built from git, quite a while ago, now I
>> removed it from /usr/local/ and installed what is in f25, but I fear it
>> will be insufficient, does 3.8 cuts it for what we're testing? Humm, it
>> looks like it will:
>>
>> [root@jouet ~]# llc --version
>> LLVM (http://llvm.org/):
>>    LLVM version 3.8.0
>>
>> But I'm now running the container based tests to send a pull req, will
>> check later, after that.
> Not really, Wang, we need to update that feature detection test to state what
> is the minimum required LLVM/clang version, one that has those functions,
> which, unfortunately, isn't the one in the latest fedora, fedora 25:

I'll set the minimum required LLVM version to 3.9, and report
warning when LLVM is too old. However, since LLVM interface is
keep changing, finally we will have problem if we want to support
2 or 3 different clang/LLVM. We should keep moving minimum
requirement LLVM version if we don't want to see '#ifdef's
spread in our code.

Thank you.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* [tip:perf/core] perf tools: Pass context to perf hook functions
  2016-11-26  7:03 ` [PATCH v3 05/30] perf tools: Pass context to perf hook functions Wang Nan
@ 2016-12-06  8:21   ` tip-bot for Wang Nan
  0 siblings, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-06  8:21 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hekuang, wangnan0, linux-kernel, lizefan, joe, ast, acme, mingo,
	jolsa, hpa, tglx

Commit-ID:  8ad85e9e6fdaf996bf3ff60303ea00e696bcdd36
Gitweb:     http://git.kernel.org/tip/8ad85e9e6fdaf996bf3ff60303ea00e696bcdd36
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:29 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 5 Dec 2016 15:51:42 -0300

perf tools: Pass context to perf hook functions

Pass a pointer to perf hook functions so they receive context
information during setup.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-6-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/perf-hooks.c | 14 +++++++++-----
 tools/perf/util/perf-hooks.c  | 10 +++++++---
 tools/perf/util/perf-hooks.h  |  6 ++++--
 3 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/tools/perf/tests/perf-hooks.c b/tools/perf/tests/perf-hooks.c
index 9338cb2..665ecc1 100644
--- a/tools/perf/tests/perf-hooks.c
+++ b/tools/perf/tests/perf-hooks.c
@@ -15,13 +15,13 @@ static void sigsegv_handler(int sig __maybe_unused)
 	exit(-1);
 }
 
-static int hook_flags;
 
-static void the_hook(void)
+static void the_hook(void *_hook_flags)
 {
+	int *hook_flags = _hook_flags;
 	int *p = NULL;
 
-	hook_flags = 1234;
+	*hook_flags = 1234;
 
 	/* Generate a segfault, test perf_hooks__recover */
 	*p = 0;
@@ -29,13 +29,17 @@ static void the_hook(void)
 
 int test__perf_hooks(int subtest __maybe_unused)
 {
+	int hook_flags = 0;
+
 	signal(SIGSEGV, sigsegv_handler);
-	perf_hooks__set_hook("test", the_hook);
+	perf_hooks__set_hook("test", the_hook, &hook_flags);
 	perf_hooks__invoke_test();
 
 	/* hook is triggered? */
-	if (hook_flags != 1234)
+	if (hook_flags != 1234) {
+		pr_debug("Setting failed: %d (%p)\n", hook_flags, &hook_flags);
 		return TEST_FAIL;
+	}
 
 	/* the buggy hook is removed? */
 	if (perf_hooks__get_hook("test"))
diff --git a/tools/perf/util/perf-hooks.c b/tools/perf/util/perf-hooks.c
index 4ce88e3..cb36830 100644
--- a/tools/perf/util/perf-hooks.c
+++ b/tools/perf/util/perf-hooks.c
@@ -27,7 +27,7 @@ void perf_hooks__invoke(const struct perf_hook_desc *desc)
 		*(current_perf_hook->p_hook_func) = NULL;
 	} else {
 		current_perf_hook = desc;
-		(**desc->p_hook_func)();
+		(**desc->p_hook_func)(desc->hook_ctx);
 	}
 	current_perf_hook = NULL;
 }
@@ -41,7 +41,9 @@ void perf_hooks__recover(void)
 #define PERF_HOOK(name)					\
 perf_hook_func_t __perf_hook_func_##name = NULL;	\
 struct perf_hook_desc __perf_hook_desc_##name =		\
-	{.hook_name = #name, .p_hook_func = &__perf_hook_func_##name};
+	{.hook_name = #name,				\
+	 .p_hook_func = &__perf_hook_func_##name,	\
+	 .hook_ctx = NULL};
 #include "perf-hooks-list.h"
 #undef PERF_HOOK
 
@@ -54,7 +56,8 @@ static struct perf_hook_desc *perf_hooks[] = {
 #undef PERF_HOOK
 
 int perf_hooks__set_hook(const char *hook_name,
-			 perf_hook_func_t hook_func)
+			 perf_hook_func_t hook_func,
+			 void *hook_ctx)
 {
 	unsigned int i;
 
@@ -65,6 +68,7 @@ int perf_hooks__set_hook(const char *hook_name,
 		if (*(perf_hooks[i]->p_hook_func))
 			pr_warning("Overwrite existing hook: %s\n", hook_name);
 		*(perf_hooks[i]->p_hook_func) = hook_func;
+		perf_hooks[i]->hook_ctx = hook_ctx;
 		return 0;
 	}
 	return -ENOENT;
diff --git a/tools/perf/util/perf-hooks.h b/tools/perf/util/perf-hooks.h
index 1d482b2..838d579 100644
--- a/tools/perf/util/perf-hooks.h
+++ b/tools/perf/util/perf-hooks.h
@@ -5,10 +5,11 @@
 extern "C" {
 #endif
 
-typedef void (*perf_hook_func_t)(void);
+typedef void (*perf_hook_func_t)(void *ctx);
 struct perf_hook_desc {
 	const char * const hook_name;
 	perf_hook_func_t * const p_hook_func;
+	void *hook_ctx;
 };
 
 extern void perf_hooks__invoke(const struct perf_hook_desc *);
@@ -26,7 +27,8 @@ static inline void perf_hooks__invoke_##name(void)	\
 
 extern int
 perf_hooks__set_hook(const char *hook_name,
-		     perf_hook_func_t hook_func);
+		     perf_hook_func_t hook_func,
+		     void *hook_ctx);
 
 extern perf_hook_func_t
 perf_hooks__get_hook(const char *hook_name);

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] perf llvm: Extract helpers in llvm-utils.c
  2016-11-26  7:03 ` [PATCH v3 06/30] perf llvm: Extract helpers in llvm-utils.c Wang Nan
@ 2016-12-06  8:21   ` tip-bot for Wang Nan
  0 siblings, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-06  8:21 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, ast, joe, hekuang, lizefan, wangnan0, acme, tglx, mingo,
	linux-kernel, hpa

Commit-ID:  2bd42de0e196f89994cbae1990d2c7c5a9b6a529
Gitweb:     http://git.kernel.org/tip/2bd42de0e196f89994cbae1990d2c7c5a9b6a529
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:30 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 5 Dec 2016 15:51:42 -0300

perf llvm: Extract helpers in llvm-utils.c

The following commits will use builtin clang to compile BPF scripts.

llvm__get_kbuild_opts() and llvm__get_nr_cpus() are extracted to help
building '-DKERNEL_VERSION_CODE' and '-D__NR_CPUS__' macros.

Doing object dumping in bpf loader, so further builtin clang compiling
needn't consider it.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-7-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/bpf-loader.c |  4 +++
 tools/perf/util/llvm-utils.c | 76 +++++++++++++++++++++++++++++++++-----------
 tools/perf/util/llvm-utils.h |  6 ++++
 3 files changed, 68 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index a5fd275..cf16b941 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -90,6 +90,10 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 		if (err)
 			return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
 		obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
+
+		if (!IS_ERR(obj) && llvm_param.dump_obj)
+			llvm__dump_obj(filename, obj_buf, obj_buf_sz);
+
 		free(obj_buf);
 	} else
 		obj = bpf_object__open(filename);
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 27b6f303..b23ff44 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -7,6 +7,7 @@
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <linux/err.h>
 #include "debug.h"
 #include "llvm-utils.h"
 #include "config.h"
@@ -282,9 +283,10 @@ static const char *kinc_fetch_script =
 "rm -rf $TMPDIR\n"
 "exit $RET\n";
 
-static inline void
-get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
+void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 {
+	static char *saved_kbuild_dir;
+	static char *saved_kbuild_include_opts;
 	int err;
 
 	if (!kbuild_dir || !kbuild_include_opts)
@@ -293,10 +295,28 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 	*kbuild_dir = NULL;
 	*kbuild_include_opts = NULL;
 
+	if (saved_kbuild_dir && saved_kbuild_include_opts &&
+	    !IS_ERR(saved_kbuild_dir) && !IS_ERR(saved_kbuild_include_opts)) {
+		*kbuild_dir = strdup(saved_kbuild_dir);
+		*kbuild_include_opts = strdup(saved_kbuild_include_opts);
+
+		if (*kbuild_dir && *kbuild_include_opts)
+			return;
+
+		zfree(kbuild_dir);
+		zfree(kbuild_include_opts);
+		/*
+		 * Don't fall through: it may breaks saved_kbuild_dir and
+		 * saved_kbuild_include_opts if detect them again when
+		 * memory is low.
+		 */
+		return;
+	}
+
 	if (llvm_param.kbuild_dir && !llvm_param.kbuild_dir[0]) {
 		pr_debug("[llvm.kbuild-dir] is set to \"\" deliberately.\n");
 		pr_debug("Skip kbuild options detection.\n");
-		return;
+		goto errout;
 	}
 
 	err = detect_kbuild_dir(kbuild_dir);
@@ -306,7 +326,7 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 "Hint:\tSet correct kbuild directory using 'kbuild-dir' option in [llvm]\n"
 "     \tsection of ~/.perfconfig or set it to \"\" to suppress kbuild\n"
 "     \tdetection.\n\n");
-		return;
+		goto errout;
 	}
 
 	pr_debug("Kernel build dir is set to %s\n", *kbuild_dir);
@@ -325,14 +345,43 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 
 		free(*kbuild_dir);
 		*kbuild_dir = NULL;
-		return;
+		goto errout;
 	}
 
 	pr_debug("include option is set to %s\n", *kbuild_include_opts);
+
+	saved_kbuild_dir = strdup(*kbuild_dir);
+	saved_kbuild_include_opts = strdup(*kbuild_include_opts);
+
+	if (!saved_kbuild_dir || !saved_kbuild_include_opts) {
+		zfree(&saved_kbuild_dir);
+		zfree(&saved_kbuild_include_opts);
+	}
+	return;
+errout:
+	saved_kbuild_dir = ERR_PTR(-EINVAL);
+	saved_kbuild_include_opts = ERR_PTR(-EINVAL);
 }
 
-static void
-dump_obj(const char *path, void *obj_buf, size_t size)
+int llvm__get_nr_cpus(void)
+{
+	static int nr_cpus_avail = 0;
+	char serr[STRERR_BUFSIZE];
+
+	if (nr_cpus_avail > 0)
+		return nr_cpus_avail;
+
+	nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
+	if (nr_cpus_avail <= 0) {
+		pr_err(
+"WARNING:\tunable to get available CPUs in this system: %s\n"
+"        \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
+		nr_cpus_avail = 128;
+	}
+	return nr_cpus_avail;
+}
+
+void llvm__dump_obj(const char *path, void *obj_buf, size_t size)
 {
 	char *obj_path = strdup(path);
 	FILE *fp;
@@ -406,15 +455,9 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
 	 * This is an optional work. Even it fail we can continue our
 	 * work. Needn't to check error return.
 	 */
-	get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
+	llvm__get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
 
-	nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
-	if (nr_cpus_avail <= 0) {
-		pr_err(
-"WARNING:\tunable to get available CPUs in this system: %s\n"
-"        \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
-		nr_cpus_avail = 128;
-	}
+	nr_cpus_avail = llvm__get_nr_cpus();
 	snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d",
 		 nr_cpus_avail);
 
@@ -453,9 +496,6 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
 	free(kbuild_dir);
 	free(kbuild_include_opts);
 
-	if (llvm_param.dump_obj)
-		dump_obj(path, obj_buf, obj_buf_sz);
-
 	if (!p_obj_buf)
 		free(obj_buf);
 	else
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h
index 9f501ce..c87a2a9 100644
--- a/tools/perf/util/llvm-utils.h
+++ b/tools/perf/util/llvm-utils.h
@@ -50,4 +50,10 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, size_t *p_obj_buf_sz);
 
 /* This function is for test__llvm() use only */
 int llvm__search_clang(void);
+
+/* Following functions are reused by builtin clang support */
+void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts);
+int llvm__get_nr_cpus(void);
+
+void llvm__dump_obj(const char *path, void *obj_buf, size_t size);
 #endif

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] tools build: Add feature detection for LLVM
  2016-11-26  7:03 ` [PATCH v3 07/30] tools build: Add feature detection for LLVM Wang Nan
@ 2016-12-06  8:22   ` tip-bot for Wang Nan
  0 siblings, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-06  8:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: wangnan0, lizefan, jolsa, tglx, ast, linux-kernel, hpa, joe,
	mingo, acme, hekuang

Commit-ID:  cb40d55b595cd117ef7c1880247605875b2115e8
Gitweb:     http://git.kernel.org/tip/cb40d55b595cd117ef7c1880247605875b2115e8
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:31 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 5 Dec 2016 15:51:42 -0300

tools build: Add feature detection for LLVM

Check if basic LLVM compiling environment is ready.

Use llvm-config to detect include and library directories. Avoid using
'llvm-config --cxxflags' because its result contain some unwanted flags
like --sysroot (if LLVM is built by yocto).

Use '?=' to set LLVM_CONFIG, so explicitly passing LLVM_CONFIG to make
would override it.

Use 'llvm-config --libs BPF' to check if BPF backend is compiled in.
Since now BPF bytecode is the only required backend, no need to waste
time linking llvm and clang if BPF backend is missing. This also
introduce an implicit requirement that LLVM should be new enough.  Old
LLVM doesn't support BPF backend.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-8-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/build/feature/Makefile      | 8 ++++++++
 tools/build/feature/test-llvm.cpp | 8 ++++++++
 2 files changed, 16 insertions(+)

diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 8f668bc..c09de59 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -55,6 +55,7 @@ FILES := $(addprefix $(OUTPUT),$(FILES))
 CC := $(CROSS_COMPILE)gcc -MD
 CXX := $(CROSS_COMPILE)g++ -MD
 PKG_CONFIG := $(CROSS_COMPILE)pkg-config
+LLVM_CONFIG ?= llvm-config
 
 all: $(FILES)
 
@@ -229,6 +230,13 @@ $(OUTPUT)test-cxx.bin:
 $(OUTPUT)test-jvmti.bin:
 	$(BUILD)
 
+$(OUTPUT)test-llvm.bin:
+	$(BUILDXX) -std=gnu++11 					\
+		-I$(shell $(LLVM_CONFIG) --includedir) 		\
+		-L$(shell $(LLVM_CONFIG) --libdir)		\
+		$(shell $(LLVM_CONFIG) --libs Core BPF)		\
+		$(shell $(LLVM_CONFIG) --system-libs)
+
 -include $(OUTPUT)*.d
 
 ###############################
diff --git a/tools/build/feature/test-llvm.cpp b/tools/build/feature/test-llvm.cpp
new file mode 100644
index 0000000..d8d2cee
--- /dev/null
+++ b/tools/build/feature/test-llvm.cpp
@@ -0,0 +1,8 @@
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+int main()
+{
+	llvm::errs() << "Hello World!\n";
+	llvm::llvm_shutdown();
+	return 0;
+}

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] tools build: Add feature detection for clang
  2016-11-26  7:03 ` [PATCH v3 08/30] tools build: Add feature detection for clang Wang Nan
@ 2016-12-06  8:22   ` tip-bot for Wang Nan
  0 siblings, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-06  8:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ast, acme, hpa, wangnan0, linux-kernel, tglx, hekuang, jolsa,
	joe, lizefan, mingo

Commit-ID:  c7fb4f62e2a97bd25d555263ef501fe053edcbb6
Gitweb:     http://git.kernel.org/tip/c7fb4f62e2a97bd25d555263ef501fe053edcbb6
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:32 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 5 Dec 2016 15:51:43 -0300

tools build: Add feature detection for clang

Check if basic clang compiling environment is ready.

Doesn't like 'llvm-config --libs' which can returns llvm libraries in right
order and duplicates some libraries if necessary, there's no correspondence for
clang libraries (-lclangxxx). to avoid extra complexity and to avoid new clang
breaking libraries ordering, use --start-group and --end-group.

In this test case, manually identify required clang libs and hope it to be
stable. Putting all clang libraries here is possible (use make's wildcard), but
then feature checking becomes very slow.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-9-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/build/feature/Makefile       | 10 ++++++++++
 tools/build/feature/test-clang.cpp | 21 +++++++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index c09de59..871d553 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -237,6 +237,16 @@ $(OUTPUT)test-llvm.bin:
 		$(shell $(LLVM_CONFIG) --libs Core BPF)		\
 		$(shell $(LLVM_CONFIG) --system-libs)
 
+$(OUTPUT)test-clang.bin:
+	$(BUILDXX) -std=gnu++11 					\
+		-I$(shell $(LLVM_CONFIG) --includedir) 		\
+		-L$(shell $(LLVM_CONFIG) --libdir)		\
+		-Wl,--start-group -lclangBasic -lclangDriver	\
+		  -lclangFrontend -lclangEdit -lclangLex	\
+		  -lclangAST -Wl,--end-group 			\
+		$(shell $(LLVM_CONFIG) --libs Core option)	\
+		$(shell $(LLVM_CONFIG) --system-libs)
+
 -include $(OUTPUT)*.d
 
 ###############################
diff --git a/tools/build/feature/test-clang.cpp b/tools/build/feature/test-clang.cpp
new file mode 100644
index 0000000..e23c1b1
--- /dev/null
+++ b/tools/build/feature/test-clang.cpp
@@ -0,0 +1,21 @@
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::driver;
+
+int main()
+{
+	IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+	IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+
+	DiagnosticsEngine Diags(DiagID, &*DiagOpts);
+	Driver TheDriver("test", "bpf-pc-linux", Diags);
+
+	llvm::llvm_shutdown();
+	return 0;
+}

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] perf build: Add clang and llvm compile and linking support
  2016-11-26  7:03 ` [PATCH v3 09/30] perf build: Add clang and llvm compile and linking support Wang Nan
@ 2016-12-06  8:23   ` tip-bot for Wang Nan
  0 siblings, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-06  8:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: wangnan0, linux-kernel, acme, tglx, mingo, joe, jolsa, lizefan,
	hpa, hekuang, ast

Commit-ID:  d58ac0bf8d1e6ffbfcb0a77e459cf4737b131b75
Gitweb:     http://git.kernel.org/tip/d58ac0bf8d1e6ffbfcb0a77e459cf4737b131b75
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:33 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 5 Dec 2016 15:51:43 -0300

perf build: Add clang and llvm compile and linking support

Add necessary c++ flags and link libraries to support builtin clang and
LLVM. Add all llvm and clang libraries, so don't need to worry about
clang changes its libraries setting. However, linking perf would take
much longer than usual.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-10-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Makefile.config | 35 +++++++++++++++++++++++++++++++++++
 tools/perf/Makefile.perf   | 23 ++++++++++++++++++++++-
 tools/perf/tests/make      |  2 ++
 3 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 8a493d4..b7c9c80 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -136,6 +136,7 @@ endif
 # Treat warnings as errors unless directed not to
 ifneq ($(WERROR),0)
   CFLAGS += -Werror
+  CXXFLAGS += -Werror
 endif
 
 ifndef DEBUG
@@ -182,6 +183,13 @@ CFLAGS += -Wall
 CFLAGS += -Wextra
 CFLAGS += -std=gnu99
 
+CXXFLAGS += -std=gnu++11 -fno-exceptions -fno-rtti
+CXXFLAGS += -Wall
+CXXFLAGS += -fno-omit-frame-pointer
+CXXFLAGS += -ggdb3
+CXXFLAGS += -funwind-tables
+CXXFLAGS += -Wno-strict-aliasing
+
 # Enforce a non-executable stack, as we may regress (again) in the future by
 # adding assembler files missing the .GNU-stack linker note.
 LDFLAGS += -Wl,-z,noexecstack
@@ -783,6 +791,33 @@ ifndef NO_JVMTI
   endif
 endif
 
+USE_CXX = 0
+USE_CLANGLLVM = 0
+ifdef LIBCLANGLLVM
+  $(call feature_check,cxx)
+  ifneq ($(feature-cxx), 1)
+    msg := $(warning No g++ found, disable clang and llvm support. Please install g++)
+  else
+    $(call feature_check,llvm)
+    ifneq ($(feature-llvm), 1)
+      msg := $(warning No libLLVM found, disable clang and llvm support. Please install llvm-dev)
+    else
+      $(call feature_check,clang)
+      ifneq ($(feature-clang), 1)
+        msg := $(warning No libclang found, disable clang and llvm support. Please install libclang-dev)
+      else
+        CFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT
+        CXXFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT -I$(shell $(LLVM_CONFIG) --includedir)
+        $(call detected,CONFIG_CXX)
+        $(call detected,CONFIG_CLANGLLVM)
+	USE_CXX = 1
+	USE_LLVM = 1
+	USE_CLANG = 1
+      endif
+    endif
+  endif
+endif
+
 # Among the variables below, these:
 #   perfexecdir
 #   template_dir
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 3cb1df4..dfb20dd 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -88,6 +88,10 @@ include ../scripts/utilities.mak
 # and bypass the feature detection
 #
 # Define NO_JVMTI if you do not want jvmti agent built
+#
+# Define LIBCLANGLLVM if you DO want builtin clang and llvm support.
+# When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if
+# llvm-config is not in $PATH.
 
 # As per kernel Makefile, avoid funny character set dependencies
 unexport LC_ALL
@@ -143,6 +147,7 @@ endef
 $(call allow-override,CC,$(CROSS_COMPILE)gcc)
 $(call allow-override,AR,$(CROSS_COMPILE)ar)
 $(call allow-override,LD,$(CROSS_COMPILE)ld)
+$(call allow-override,CXX,$(CROSS_COMPILE)g++)
 
 LD += $(EXTRA_LDFLAGS)
 
@@ -151,6 +156,7 @@ HOSTLD  ?= ld
 HOSTAR  ?= ar
 
 PKG_CONFIG = $(CROSS_COMPILE)pkg-config
+LLVM_CONFIG ?= llvm-config
 
 RM      = rm -f
 LN      = ln -f
@@ -338,6 +344,21 @@ endif
 
 LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
 
+ifeq ($(USE_CLANG), 1)
+  CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization
+  LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) --libdir)/libclang$(l).a))
+  LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group
+endif
+
+ifeq ($(USE_LLVM), 1)
+  LIBLLVM = $(shell $(LLVM_CONFIG) --libs all) $(shell $(LLVM_CONFIG) --system-libs)
+  LIBS += -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM)
+endif
+
+ifeq ($(USE_CXX), 1)
+  LIBS += -lstdc++
+endif
+
 export INSTALL SHELL_PATH
 
 ### Build rules
@@ -356,7 +377,7 @@ strip: $(PROGRAMS) $(OUTPUT)perf
 
 PERF_IN := $(OUTPUT)perf-in.o
 
-export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
+export srctree OUTPUT RM CC CXX LD AR CFLAGS CXXFLAGS V BISON FLEX AWK
 export HOSTCC HOSTLD HOSTAR
 include $(srctree)/tools/build/Makefile.include
 
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 08ed7f1..aa49b66 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -83,6 +83,7 @@ make_no_libbpf	    := NO_LIBBPF=1
 make_no_libcrypto   := NO_LIBCRYPTO=1
 make_with_babeltrace:= LIBBABELTRACE=1
 make_no_sdt	    := NO_SDT=1
+make_with_clangllvm := LIBCLANGLLVM=1
 make_tags           := tags
 make_cscope         := cscope
 make_help           := help
@@ -139,6 +140,7 @@ run += make_no_libbionic
 run += make_no_auxtrace
 run += make_no_libbpf
 run += make_with_babeltrace
+run += make_with_clangllvm
 run += make_help
 run += make_doc
 run += make_perf_o

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] perf clang: Add builtin clang support ant test case
  2016-11-26  7:03 ` [PATCH v3 10/30] perf clang: Add builtin clang support ant test case Wang Nan
  2016-11-26 17:17   ` Alexei Starovoitov
  2016-12-02 15:44   ` Arnaldo Carvalho de Melo
@ 2016-12-06  8:23   ` tip-bot for Wang Nan
  2 siblings, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-06  8:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hekuang, jolsa, tglx, joe, hpa, ast, linux-kernel, acme,
	wangnan0, mingo, lizefan

Commit-ID:  00b86691c77c6576861b82a3cfe4d609800758fe
Gitweb:     http://git.kernel.org/tip/00b86691c77c6576861b82a3cfe4d609800758fe
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:34 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 5 Dec 2016 15:51:43 -0300

perf clang: Add builtin clang support ant test case

Add basic clang support in clang.cpp and test__clang() testcase. The
first testcase checks if builtin clang is able to generate LLVM IR.

tests/clang.c is a proxy. Real testcase resides in
utils/c++/clang-test.cpp in c++ and exports C interface to perf test
subsystem.

Test result:

   $ perf test -v clang
   51: builtin clang support                               :
   51.1: Test builtin clang compile C source to IR              :
   --- start ---
   test child forked, pid 13215
   test child finished with 0
   ---- end ----
   Test builtin clang support subtest 0: Ok

Committer note:

Make sure you've enabled CLANG and LLVM builtin support by setting
the LIBCLANGLLVM variable on the make command line, e.g.:

  make LIBCLANGLLVM=1 O=/tmp/build/perf -C tools/perf install-bin

Otherwise you'll get this when trying to do the 'perf test' call above:

  # perf test clang
  51: builtin clang support                      : Skip (not compiled in)
  #

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-11-wangnan0@huawei.com
[ Removed "Test" from descriptions, redundant and already removed from all the other entries ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/Build             |  1 +
 tools/perf/tests/builtin-test.c    |  9 ++++
 tools/perf/tests/clang.c           | 42 +++++++++++++++++
 tools/perf/tests/tests.h           |  3 ++
 tools/perf/util/Build              |  2 +
 tools/perf/util/c++/Build          |  2 +
 tools/perf/util/c++/clang-c.h      | 16 +++++++
 tools/perf/util/c++/clang-test.cpp | 31 ++++++++++++
 tools/perf/util/c++/clang.cpp      | 96 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/c++/clang.h        | 16 +++++++
 10 files changed, 218 insertions(+)

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index af3ec94..6676c2d 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -43,6 +43,7 @@ perf-y += sdt.o
 perf-y += is_printable_array.o
 perf-y += bitmap.o
 perf-y += perf-hooks.o
+perf-y += clang.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
 	$(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index d1bec04..2360520 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -234,6 +234,15 @@ static struct test generic_tests[] = {
 		.func = test__perf_hooks,
 	},
 	{
+		.desc = "builtin clang support",
+		.func = test__clang,
+		.subtest = {
+			.skip_if_fail	= true,
+			.get_nr		= test__clang_subtest_get_nr,
+			.get_desc	= test__clang_subtest_get_desc,
+		}
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
new file mode 100644
index 0000000..636d6d0
--- /dev/null
+++ b/tools/perf/tests/clang.c
@@ -0,0 +1,42 @@
+#include "tests.h"
+#include "debug.h"
+#include "util.h"
+#include "c++/clang-c.h"
+
+static struct {
+	int (*func)(void);
+	const char *desc;
+} clang_testcase_table[] = {
+#ifdef HAVE_LIBCLANGLLVM_SUPPORT
+	{
+		.func = test__clang_to_IR,
+		.desc = "builtin clang compile C source to IR",
+	},
+#endif
+};
+
+int test__clang_subtest_get_nr(void)
+{
+	return (int)ARRAY_SIZE(clang_testcase_table);
+}
+
+const char *test__clang_subtest_get_desc(int i)
+{
+	if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
+		return NULL;
+	return clang_testcase_table[i].desc;
+}
+
+#ifndef HAVE_LIBCLANGLLVM_SUPPORT
+int test__clang(int i __maybe_unused)
+{
+	return TEST_SKIP;
+}
+#else
+int test__clang(int i __maybe_unused)
+{
+	if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
+		return TEST_FAIL;
+	return clang_testcase_table[i].func();
+}
+#endif
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 3a1f98f..0d7b251 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -92,6 +92,9 @@ int test__sdt_event(int subtest);
 int test__is_printable_array(int subtest);
 int test__bitmap_print(int subtest);
 int test__perf_hooks(int subtest);
+int test__clang(int subtest);
+const char *test__clang_subtest_get_desc(int subtest);
+int test__clang_subtest_get_nr(void);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index bdad82a..3840e3a 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -126,6 +126,8 @@ endif
 
 libperf-y += perf-hooks.o
 
+libperf-$(CONFIG_CXX) += c++/
+
 CFLAGS_config.o   += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
 # avoid compiler warnings in 32-bit mode
 CFLAGS_genelf_debug.o  += -Wno-packed
diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
new file mode 100644
index 0000000..988fef1
--- /dev/null
+++ b/tools/perf/util/c++/Build
@@ -0,0 +1,2 @@
+libperf-$(CONFIG_CLANGLLVM) += clang.o
+libperf-$(CONFIG_CLANGLLVM) += clang-test.o
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
new file mode 100644
index 0000000..dcde4b5
--- /dev/null
+++ b/tools/perf/util/c++/clang-c.h
@@ -0,0 +1,16 @@
+#ifndef PERF_UTIL_CLANG_C_H
+#define PERF_UTIL_CLANG_C_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void perf_clang__init(void);
+extern void perf_clang__cleanup(void);
+
+extern int test__clang_to_IR(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
new file mode 100644
index 0000000..3da6bfa
--- /dev/null
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -0,0 +1,31 @@
+#include "clang.h"
+#include "clang-c.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/LLVMContext.h"
+
+class perf_clang_scope {
+public:
+	explicit perf_clang_scope() {perf_clang__init();}
+	~perf_clang_scope() {perf_clang__cleanup();}
+};
+
+extern "C" {
+
+int test__clang_to_IR(void)
+{
+	perf_clang_scope _scope;
+
+	std::unique_ptr<llvm::Module> M =
+		perf::getModuleFromSource("perf-test.c",
+					  "int myfunc(void) {return 1;}");
+
+	if (!M)
+		return -1;
+
+	for (llvm::Function& F : *M)
+		if (F.getName() == "myfunc")
+			return 0;
+	return -1;
+}
+
+}
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
new file mode 100644
index 0000000..c17b117
--- /dev/null
+++ b/tools/perf/util/c++/clang.cpp
@@ -0,0 +1,96 @@
+/*
+ * llvm C frontend for perf. Support dynamically compile C file
+ *
+ * Inspired by clang example code:
+ * http://llvm.org/svn/llvm-project/cfe/trunk/examples/clang-interpreter/main.cpp
+ *
+ * Copyright (C) 2016 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2016 Huawei Inc.
+ */
+
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/ManagedStatic.h"
+#include <memory>
+
+#include "clang.h"
+#include "clang-c.h"
+
+namespace perf {
+
+static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
+
+using namespace clang;
+
+static vfs::InMemoryFileSystem *
+buildVFS(StringRef& Name, StringRef& Content)
+{
+	vfs::InMemoryFileSystem *VFS = new vfs::InMemoryFileSystem(true);
+	VFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
+	return VFS;
+}
+
+static CompilerInvocation *
+createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
+{
+	llvm::opt::ArgStringList CCArgs {
+		"-cc1",
+		"-triple", "bpf-pc-linux",
+		"-fsyntax-only",
+		"-ferror-limit", "19",
+		"-fmessage-length", "127",
+		"-O2",
+		"-nostdsysteminc",
+		"-nobuiltininc",
+		"-vectorize-loops",
+		"-vectorize-slp",
+		"-Wno-unused-value",
+		"-Wno-pointer-sign",
+		"-x", "c"};
+	CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);
+
+	FrontendOptions& Opts = CI->getFrontendOpts();
+	Opts.Inputs.clear();
+	Opts.Inputs.emplace_back(Path, IK_C);
+	return CI;
+}
+
+std::unique_ptr<llvm::Module>
+getModuleFromSource(StringRef Name, StringRef Content)
+{
+	CompilerInstance Clang;
+	Clang.createDiagnostics();
+
+	IntrusiveRefCntPtr<vfs::FileSystem> VFS = buildVFS(Name, Content);
+	Clang.setVirtualFileSystem(&*VFS);
+
+	IntrusiveRefCntPtr<CompilerInvocation> CI =
+		createCompilerInvocation(Name, Clang.getDiagnostics());
+	Clang.setInvocation(&*CI);
+
+	std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
+	if (!Clang.ExecuteAction(*Act))
+		return std::unique_ptr<llvm::Module>(nullptr);
+
+	return Act->takeModule();
+}
+
+}
+
+extern "C" {
+void perf_clang__init(void)
+{
+	perf::LLVMCtx.reset(new llvm::LLVMContext());
+}
+
+void perf_clang__cleanup(void)
+{
+	perf::LLVMCtx.reset(nullptr);
+	llvm::llvm_shutdown();
+}
+}
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
new file mode 100644
index 0000000..f64483b
--- /dev/null
+++ b/tools/perf/util/c++/clang.h
@@ -0,0 +1,16 @@
+#ifndef PERF_UTIL_CLANG_H
+#define PERF_UTIL_CLANG_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include <memory>
+namespace perf {
+
+using namespace llvm;
+
+std::unique_ptr<Module>
+getModuleFromSource(StringRef Name, StringRef Content);
+
+}
+#endif

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] perf clang: Use real file system for #include
  2016-11-26  7:03 ` [PATCH v3 11/30] perf clang: Use real file system for #include Wang Nan
@ 2016-12-06  8:24   ` tip-bot for Wang Nan
  0 siblings, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-06  8:24 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, mingo, hekuang, tglx, acme, linux-kernel, hpa, wangnan0,
	lizefan, joe, ast

Commit-ID:  77dfa84a843c0bc935a6c8664f2556573e30845f
Gitweb:     http://git.kernel.org/tip/77dfa84a843c0bc935a6c8664f2556573e30845f
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:35 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 5 Dec 2016 15:51:44 -0300

perf clang: Use real file system for #include

Utilize clang's OverlayFileSystem facility, allow CompilerInstance to
access real file system.

With this patch the '#include' directive can be used.

Add a new getModuleFromSource for real file.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-12-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/c++/clang.cpp | 44 +++++++++++++++++++++++++++++++------------
 tools/perf/util/c++/clang.h   |  3 +++
 2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index c17b117..cf96199 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -15,6 +15,7 @@
 #include "clang/Tooling/Tooling.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Option/Option.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/ManagedStatic.h"
 #include <memory>
 
@@ -27,14 +28,6 @@ static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
 
 using namespace clang;
 
-static vfs::InMemoryFileSystem *
-buildVFS(StringRef& Name, StringRef& Content)
-{
-	vfs::InMemoryFileSystem *VFS = new vfs::InMemoryFileSystem(true);
-	VFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
-	return VFS;
-}
-
 static CompilerInvocation *
 createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
 {
@@ -60,17 +53,17 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
 	return CI;
 }
 
-std::unique_ptr<llvm::Module>
-getModuleFromSource(StringRef Name, StringRef Content)
+static std::unique_ptr<llvm::Module>
+getModuleFromSource(StringRef Path,
+		    IntrusiveRefCntPtr<vfs::FileSystem> VFS)
 {
 	CompilerInstance Clang;
 	Clang.createDiagnostics();
 
-	IntrusiveRefCntPtr<vfs::FileSystem> VFS = buildVFS(Name, Content);
 	Clang.setVirtualFileSystem(&*VFS);
 
 	IntrusiveRefCntPtr<CompilerInvocation> CI =
-		createCompilerInvocation(Name, Clang.getDiagnostics());
+		createCompilerInvocation(Path, Clang.getDiagnostics());
 	Clang.setInvocation(&*CI);
 
 	std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
@@ -80,6 +73,33 @@ getModuleFromSource(StringRef Name, StringRef Content)
 	return Act->takeModule();
 }
 
+std::unique_ptr<llvm::Module>
+getModuleFromSource(StringRef Name, StringRef Content)
+{
+	using namespace vfs;
+
+	llvm::IntrusiveRefCntPtr<OverlayFileSystem> OverlayFS(
+			new OverlayFileSystem(getRealFileSystem()));
+	llvm::IntrusiveRefCntPtr<InMemoryFileSystem> MemFS(
+			new InMemoryFileSystem(true));
+
+	/*
+	 * pushOverlay helps setting working dir for MemFS. Must call
+	 * before addFile.
+	 */
+	OverlayFS->pushOverlay(MemFS);
+	MemFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
+
+	return getModuleFromSource(Name, OverlayFS);
+}
+
+std::unique_ptr<llvm::Module>
+getModuleFromSource(StringRef Path)
+{
+	IntrusiveRefCntPtr<vfs::FileSystem> VFS(vfs::getRealFileSystem());
+	return getModuleFromSource(Path, VFS);
+}
+
 }
 
 extern "C" {
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index f64483b..90aff01 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -12,5 +12,8 @@ using namespace llvm;
 std::unique_ptr<Module>
 getModuleFromSource(StringRef Name, StringRef Content);
 
+std::unique_ptr<Module>
+getModuleFromSource(StringRef Path);
+
 }
 #endif

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] perf clang: Allow passing CFLAGS to builtin clang
  2016-11-26  7:03 ` [PATCH v3 12/30] perf clang: Allow passing CFLAGS to builtin clang Wang Nan
@ 2016-12-06  8:25   ` tip-bot for Wang Nan
  0 siblings, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-06  8:25 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hekuang, hpa, ast, wangnan0, jolsa, acme, joe, linux-kernel,
	tglx, mingo, lizefan

Commit-ID:  a9495fe9dc63bee1166772b6f10e199ef1747892
Gitweb:     http://git.kernel.org/tip/a9495fe9dc63bee1166772b6f10e199ef1747892
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:36 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 5 Dec 2016 15:51:44 -0300

perf clang: Allow passing CFLAGS to builtin clang

Improve getModuleFromSource() API to accept a cflags list. This feature
will be used to pass LINUX_VERSION_CODE and -I flags.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-13-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/c++/clang-test.cpp |  5 +++--
 tools/perf/util/c++/clang.cpp      | 21 +++++++++++++--------
 tools/perf/util/c++/clang.h        |  8 ++++++--
 3 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
index 3da6bfa..0f484fb 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -16,8 +16,9 @@ int test__clang_to_IR(void)
 	perf_clang_scope _scope;
 
 	std::unique_ptr<llvm::Module> M =
-		perf::getModuleFromSource("perf-test.c",
-					  "int myfunc(void) {return 1;}");
+		perf::getModuleFromSource({"-DRESULT=1"},
+					  "perf-test.c",
+					  "int myfunc(void) {return RESULT;}");
 
 	if (!M)
 		return -1;
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index cf96199..715ca0a 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -29,7 +29,8 @@ static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
 using namespace clang;
 
 static CompilerInvocation *
-createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
+createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
+			 DiagnosticsEngine& Diags)
 {
 	llvm::opt::ArgStringList CCArgs {
 		"-cc1",
@@ -45,6 +46,8 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
 		"-Wno-unused-value",
 		"-Wno-pointer-sign",
 		"-x", "c"};
+
+	CCArgs.append(CFlags.begin(), CFlags.end());
 	CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);
 
 	FrontendOptions& Opts = CI->getFrontendOpts();
@@ -54,8 +57,8 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
 }
 
 static std::unique_ptr<llvm::Module>
-getModuleFromSource(StringRef Path,
-		    IntrusiveRefCntPtr<vfs::FileSystem> VFS)
+getModuleFromSource(llvm::opt::ArgStringList CFlags,
+		    StringRef Path, IntrusiveRefCntPtr<vfs::FileSystem> VFS)
 {
 	CompilerInstance Clang;
 	Clang.createDiagnostics();
@@ -63,7 +66,8 @@ getModuleFromSource(StringRef Path,
 	Clang.setVirtualFileSystem(&*VFS);
 
 	IntrusiveRefCntPtr<CompilerInvocation> CI =
-		createCompilerInvocation(Path, Clang.getDiagnostics());
+		createCompilerInvocation(std::move(CFlags), Path,
+					 Clang.getDiagnostics());
 	Clang.setInvocation(&*CI);
 
 	std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
@@ -74,7 +78,8 @@ getModuleFromSource(StringRef Path,
 }
 
 std::unique_ptr<llvm::Module>
-getModuleFromSource(StringRef Name, StringRef Content)
+getModuleFromSource(llvm::opt::ArgStringList CFlags,
+		    StringRef Name, StringRef Content)
 {
 	using namespace vfs;
 
@@ -90,14 +95,14 @@ getModuleFromSource(StringRef Name, StringRef Content)
 	OverlayFS->pushOverlay(MemFS);
 	MemFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
 
-	return getModuleFromSource(Name, OverlayFS);
+	return getModuleFromSource(std::move(CFlags), Name, OverlayFS);
 }
 
 std::unique_ptr<llvm::Module>
-getModuleFromSource(StringRef Path)
+getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
 {
 	IntrusiveRefCntPtr<vfs::FileSystem> VFS(vfs::getRealFileSystem());
-	return getModuleFromSource(Path, VFS);
+	return getModuleFromSource(std::move(CFlags), Path, VFS);
 }
 
 }
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index 90aff01..b4fc2a9 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -4,16 +4,20 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Option/Option.h"
 #include <memory>
+
 namespace perf {
 
 using namespace llvm;
 
 std::unique_ptr<Module>
-getModuleFromSource(StringRef Name, StringRef Content);
+getModuleFromSource(opt::ArgStringList CFlags,
+		    StringRef Name, StringRef Content);
 
 std::unique_ptr<Module>
-getModuleFromSource(StringRef Path);
+getModuleFromSource(opt::ArgStringList CFlags,
+		    StringRef Path);
 
 }
 #endif

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] perf clang: Update test case to use real BPF script
  2016-11-26  7:03 ` [PATCH v3 13/30] perf clang: Update test case to use real BPF script Wang Nan
@ 2016-12-06  8:25   ` tip-bot for Wang Nan
  0 siblings, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-06  8:25 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: joe, jolsa, wangnan0, hpa, ast, mingo, linux-kernel, hekuang,
	acme, lizefan, tglx

Commit-ID:  e67d52d411c3562263735479db2efd2ebd178db9
Gitweb:     http://git.kernel.org/tip/e67d52d411c3562263735479db2efd2ebd178db9
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:37 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 5 Dec 2016 15:51:44 -0300

perf clang: Update test case to use real BPF script

Allow C++ code to use util.h and tests/llvm.h. Let 'perf test' compile a
real BPF script.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-14-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Makefile.config         | 27 +++++++++++++++------------
 tools/perf/tests/llvm.h            |  7 +++++++
 tools/perf/util/c++/clang-test.cpp | 17 ++++++++++++++---
 tools/perf/util/util-cxx.h         | 26 ++++++++++++++++++++++++++
 4 files changed, 62 insertions(+), 15 deletions(-)

diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index b7c9c80..09c2a98 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -212,24 +212,27 @@ ifeq ($(DEBUG),0)
   endif
 endif
 
-CFLAGS += -I$(src-perf)/util/include
-CFLAGS += -I$(src-perf)/arch/$(ARCH)/include
-CFLAGS += -I$(srctree)/tools/include/uapi
-CFLAGS += -I$(srctree)/tools/include/
-CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
-CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
-CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/
+INC_FLAGS += -I$(src-perf)/util/include
+INC_FLAGS += -I$(src-perf)/arch/$(ARCH)/include
+INC_FLAGS += -I$(srctree)/tools/include/uapi
+INC_FLAGS += -I$(srctree)/tools/include/
+INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
+INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
+INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/
 
 # $(obj-perf)      for generated common-cmds.h
 # $(obj-perf)/util for generated bison/flex headers
 ifneq ($(OUTPUT),)
-CFLAGS += -I$(obj-perf)/util
-CFLAGS += -I$(obj-perf)
+INC_FLAGS += -I$(obj-perf)/util
+INC_FLAGS += -I$(obj-perf)
 endif
 
-CFLAGS += -I$(src-perf)/util
-CFLAGS += -I$(src-perf)
-CFLAGS += -I$(srctree)/tools/lib/
+INC_FLAGS += -I$(src-perf)/util
+INC_FLAGS += -I$(src-perf)
+INC_FLAGS += -I$(srctree)/tools/lib/
+
+CFLAGS   += $(INC_FLAGS)
+CXXFLAGS += $(INC_FLAGS)
 
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
index 0eaa604..b835717 100644
--- a/tools/perf/tests/llvm.h
+++ b/tools/perf/tests/llvm.h
@@ -1,6 +1,10 @@
 #ifndef PERF_TEST_LLVM_H
 #define PERF_TEST_LLVM_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include <stddef.h> /* for size_t */
 #include <stdbool.h> /* for bool */
 
@@ -20,4 +24,7 @@ enum test_llvm__testcase {
 int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz,
 			     enum test_llvm__testcase index, bool force,
 			     bool *should_load_fail);
+#ifdef __cplusplus
+}
+#endif
 #endif
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
index 0f484fb..d84e760 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -3,6 +3,10 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/LLVMContext.h"
 
+#include <util-cxx.h>
+#include <tests/llvm.h>
+#include <string>
+
 class perf_clang_scope {
 public:
 	explicit perf_clang_scope() {perf_clang__init();}
@@ -14,17 +18,24 @@ extern "C" {
 int test__clang_to_IR(void)
 {
 	perf_clang_scope _scope;
+	unsigned int kernel_version;
+
+	if (fetch_kernel_version(&kernel_version, NULL, 0))
+		return -1;
+
+	std::string cflag_kver("-DLINUX_VERSION_CODE=" +
+				std::to_string(kernel_version));
 
 	std::unique_ptr<llvm::Module> M =
-		perf::getModuleFromSource({"-DRESULT=1"},
+		perf::getModuleFromSource({cflag_kver.c_str()},
 					  "perf-test.c",
-					  "int myfunc(void) {return RESULT;}");
+					  test_llvm__bpf_base_prog);
 
 	if (!M)
 		return -1;
 
 	for (llvm::Function& F : *M)
-		if (F.getName() == "myfunc")
+		if (F.getName() == "bpf_func__SyS_epoll_wait")
 			return 0;
 	return -1;
 }
diff --git a/tools/perf/util/util-cxx.h b/tools/perf/util/util-cxx.h
new file mode 100644
index 0000000..0e0e019
--- /dev/null
+++ b/tools/perf/util/util-cxx.h
@@ -0,0 +1,26 @@
+/*
+ * Support C++ source use utilities defined in util.h
+ */
+
+#ifndef PERF_UTIL_UTIL_CXX_H
+#define PERF_UTIL_UTIL_CXX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Now 'new' is the only C++ keyword found in util.h:
+ * in tools/include/linux/rbtree.h
+ *
+ * Other keywords, like class and delete, should be
+ * redefined if necessary.
+ */
+#define new _new
+#include "util.h"
+#undef new
+
+#ifdef __cplusplus
+}
+#endif
+#endif

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] perf clang: Support compile IR to BPF object and add testcase
  2016-11-26  7:03 ` [PATCH v3 14/30] perf clang: Support compile IR to BPF object and add testcase Wang Nan
  2016-11-26 17:25   ` Alexei Starovoitov
@ 2016-12-06  8:26   ` tip-bot for Wang Nan
  1 sibling, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-06  8:26 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ast, hpa, mingo, wangnan0, acme, lizefan, jolsa, hekuang, joe,
	linux-kernel, tglx

Commit-ID:  5e08a76525b8f5e9aeb8b27d0466614abec070a9
Gitweb:     http://git.kernel.org/tip/5e08a76525b8f5e9aeb8b27d0466614abec070a9
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:38 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 5 Dec 2016 15:51:44 -0300

perf clang: Support compile IR to BPF object and add testcase

getBPFObjectFromModule() is introduced to compile LLVM IR(Module)
to BPF object. Add new testcase for it.

Test result:
  $ ./buildperf/perf test -v clang
  51: builtin clang support                               :
  51.1: builtin clang compile C source to IR              :
  --- start ---
  test child forked, pid 21822
  test child finished with 0
  ---- end ----
  builtin clang support subtest 0: Ok
  51.2: builtin clang compile C source to ELF object      :
  --- start ---
  test child forked, pid 21823
  test child finished with 0
  ---- end ----
  builtin clang support subtest 1: Ok

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-15-wangnan0@huawei.com
[ Remove redundant "Test" from entry descriptions ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/clang.c           |  6 ++++-
 tools/perf/util/c++/clang-c.h      |  1 +
 tools/perf/util/c++/clang-test.cpp | 31 +++++++++++++++++++++-----
 tools/perf/util/c++/clang.cpp      | 45 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/c++/clang.h        |  3 +++
 5 files changed, 79 insertions(+), 7 deletions(-)

diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
index 636d6d0..f853e24 100644
--- a/tools/perf/tests/clang.c
+++ b/tools/perf/tests/clang.c
@@ -12,6 +12,10 @@ static struct {
 		.func = test__clang_to_IR,
 		.desc = "builtin clang compile C source to IR",
 	},
+	{
+		.func = test__clang_to_obj,
+		.desc = "builtin clang compile C source to ELF object",
+	},
 #endif
 };
 
@@ -33,7 +37,7 @@ int test__clang(int i __maybe_unused)
 	return TEST_SKIP;
 }
 #else
-int test__clang(int i __maybe_unused)
+int test__clang(int i)
 {
 	if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
 		return TEST_FAIL;
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index dcde4b5..22b3936 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -9,6 +9,7 @@ extern void perf_clang__init(void);
 extern void perf_clang__cleanup(void);
 
 extern int test__clang_to_IR(void);
+extern int test__clang_to_obj(void);
 
 #ifdef __cplusplus
 }
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
index d84e760..9b11e8c 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -13,15 +13,13 @@ public:
 	~perf_clang_scope() {perf_clang__cleanup();}
 };
 
-extern "C" {
-
-int test__clang_to_IR(void)
+static std::unique_ptr<llvm::Module>
+__test__clang_to_IR(void)
 {
-	perf_clang_scope _scope;
 	unsigned int kernel_version;
 
 	if (fetch_kernel_version(&kernel_version, NULL, 0))
-		return -1;
+		return std::unique_ptr<llvm::Module>(nullptr);
 
 	std::string cflag_kver("-DLINUX_VERSION_CODE=" +
 				std::to_string(kernel_version));
@@ -30,14 +28,35 @@ int test__clang_to_IR(void)
 		perf::getModuleFromSource({cflag_kver.c_str()},
 					  "perf-test.c",
 					  test_llvm__bpf_base_prog);
+	return M;
+}
+
+extern "C" {
+int test__clang_to_IR(void)
+{
+	perf_clang_scope _scope;
 
+	auto M = __test__clang_to_IR();
 	if (!M)
 		return -1;
-
 	for (llvm::Function& F : *M)
 		if (F.getName() == "bpf_func__SyS_epoll_wait")
 			return 0;
 	return -1;
 }
 
+int test__clang_to_obj(void)
+{
+	perf_clang_scope _scope;
+
+	auto M = __test__clang_to_IR();
+	if (!M)
+		return -1;
+
+	auto Buffer = perf::getBPFObjectFromModule(&*M);
+	if (!Buffer)
+		return -1;
+	return 0;
+}
+
 }
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 715ca0a..2a1a75d 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -13,10 +13,15 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
 #include <memory>
 
 #include "clang.h"
@@ -105,12 +110,52 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
 	return getModuleFromSource(std::move(CFlags), Path, VFS);
 }
 
+std::unique_ptr<llvm::SmallVectorImpl<char>>
+getBPFObjectFromModule(llvm::Module *Module)
+{
+	using namespace llvm;
+
+	std::string TargetTriple("bpf-pc-linux");
+	std::string Error;
+	const Target* Target = TargetRegistry::lookupTarget(TargetTriple, Error);
+	if (!Target) {
+		llvm::errs() << Error;
+		return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);
+	}
+
+	llvm::TargetOptions Opt;
+	TargetMachine *TargetMachine =
+		Target->createTargetMachine(TargetTriple,
+					    "generic", "",
+					    Opt, Reloc::Static);
+
+	Module->setDataLayout(TargetMachine->createDataLayout());
+	Module->setTargetTriple(TargetTriple);
+
+	std::unique_ptr<SmallVectorImpl<char>> Buffer(new SmallVector<char, 0>());
+	raw_svector_ostream ostream(*Buffer);
+
+	legacy::PassManager PM;
+	if (TargetMachine->addPassesToEmitFile(PM, ostream,
+					       TargetMachine::CGFT_ObjectFile)) {
+		llvm::errs() << "TargetMachine can't emit a file of this type\n";
+		return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);;
+	}
+	PM.run(*Module);
+
+	return std::move(Buffer);
+}
+
 }
 
 extern "C" {
 void perf_clang__init(void)
 {
 	perf::LLVMCtx.reset(new llvm::LLVMContext());
+	LLVMInitializeBPFTargetInfo();
+	LLVMInitializeBPFTarget();
+	LLVMInitializeBPFTargetMC();
+	LLVMInitializeBPFAsmPrinter();
 }
 
 void perf_clang__cleanup(void)
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index b4fc2a9..dd8b042 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -19,5 +19,8 @@ std::unique_ptr<Module>
 getModuleFromSource(opt::ArgStringList CFlags,
 		    StringRef Path);
 
+std::unique_ptr<llvm::SmallVectorImpl<char>>
+getBPFObjectFromModule(llvm::Module *Module);
+
 }
 #endif

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* [tip:perf/core] perf clang: Compile BPF script using builtin clang support
  2016-11-26  7:03 ` [PATCH v3 15/30] perf clang: Compile BPF script use builtin clang support Wang Nan
@ 2016-12-06  8:26   ` tip-bot for Wang Nan
  0 siblings, 0 replies; 73+ messages in thread
From: tip-bot for Wang Nan @ 2016-12-06  8:26 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: wangnan0, mingo, hpa, jolsa, ast, hekuang, joe, linux-kernel,
	lizefan, tglx, acme

Commit-ID:  edd695b032ba3a90c3bb07d934500b2c390a61ff
Gitweb:     http://git.kernel.org/tip/edd695b032ba3a90c3bb07d934500b2c390a61ff
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Sat, 26 Nov 2016 07:03:39 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 5 Dec 2016 15:51:45 -0300

perf clang: Compile BPF script using builtin clang support

After this patch, perf utilizes builtin clang support to build BPF
script, no longer depend on external clang, but fallbacking to it
if for some reason the builtin compiling framework fails.

Test:

  $ type clang
  -bash: type: clang: not found
  $ cat ~/.perfconfig
  $ echo '#define LINUX_VERSION_CODE 0x040700' > ./test.c
  $ cat ./tools/perf/tests/bpf-script-example.c >> ./test.c
  $ ./perf record -v --dry-run -e ./test.c 2>&1 | grep builtin
  bpf: successfull builtin compilation
  $

Can't pass cflags so unable to include kernel headers now. Will be fixed
by following commits.

Committer notes:

Make sure '-v' comes before the '-e ./test.c' in the command line otherwise the
'verbose' variable will not be set when the bpf event is parsed and thus the
pr_debug indicating a 'successfull builtin compilation' will not be output, as
the debug level (1) will be less than what 'verbose' has at that point (0).

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-16-wangnan0@huawei.com
[ Spell check/reflow successfull pr_debug string ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/bpf-loader.c  | 15 +++++++++++----
 tools/perf/util/c++/clang-c.h | 26 ++++++++++++++++++++++++++
 tools/perf/util/c++/clang.cpp | 29 +++++++++++++++++++++++++++++
 3 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index cf16b941..36c8611 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -14,11 +14,11 @@
 #include "debug.h"
 #include "bpf-loader.h"
 #include "bpf-prologue.h"
-#include "llvm-utils.h"
 #include "probe-event.h"
 #include "probe-finder.h" // for MAX_PROBES
 #include "parse-events.h"
 #include "llvm-utils.h"
+#include "c++/clang-c.h"
 
 #define DEFINE_PRINT_FN(name, level) \
 static int libbpf_##name(const char *fmt, ...)	\
@@ -86,9 +86,16 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 		void *obj_buf;
 		size_t obj_buf_sz;
 
-		err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
-		if (err)
-			return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+		perf_clang__init();
+		err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+		perf_clang__cleanup();
+		if (err) {
+			pr_warning("bpf: builtin compilation failed: %d, try external compiler\n", err);
+			err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+			if (err)
+				return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+		} else
+			pr_debug("bpf: successfull builtin compilation\n");
 		obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
 
 		if (!IS_ERR(obj) && llvm_param.dump_obj)
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 22b3936..0eadd79 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -1,16 +1,42 @@
 #ifndef PERF_UTIL_CLANG_C_H
 #define PERF_UTIL_CLANG_C_H
 
+#include <stddef.h>	/* for size_t */
+#include <util-cxx.h>	/* for __maybe_unused */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#ifdef HAVE_LIBCLANGLLVM_SUPPORT
 extern void perf_clang__init(void);
 extern void perf_clang__cleanup(void);
 
 extern int test__clang_to_IR(void);
 extern int test__clang_to_obj(void);
 
+extern int perf_clang__compile_bpf(const char *filename,
+				   void **p_obj_buf,
+				   size_t *p_obj_buf_sz);
+#else
+
+
+static inline void perf_clang__init(void) { }
+static inline void perf_clang__cleanup(void) { }
+
+static inline int test__clang_to_IR(void) { return -1; }
+static inline int test__clang_to_obj(void) { return -1;}
+
+static inline int
+perf_clang__compile_bpf(const char *filename __maybe_unused,
+			void **p_obj_buf __maybe_unused,
+			size_t *p_obj_buf_sz __maybe_unused)
+{
+	return -ENOTSUP;
+}
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 2a1a75d..1e97415 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -163,4 +163,33 @@ void perf_clang__cleanup(void)
 	perf::LLVMCtx.reset(nullptr);
 	llvm::llvm_shutdown();
 }
+
+int perf_clang__compile_bpf(const char *filename,
+			    void **p_obj_buf,
+			    size_t *p_obj_buf_sz)
+{
+	using namespace perf;
+
+	if (!p_obj_buf || !p_obj_buf_sz)
+		return -EINVAL;
+
+	llvm::opt::ArgStringList CFlags;
+	auto M = getModuleFromSource(std::move(CFlags), filename);
+	if (!M)
+		return  -EINVAL;
+	auto O = getBPFObjectFromModule(&*M);
+	if (!O)
+		return -EINVAL;
+
+	size_t size = O->size_in_bytes();
+	void *buffer;
+
+	buffer = malloc(size);
+	if (!buffer)
+		return -ENOMEM;
+	memcpy(buffer, O->data(), size);
+	*p_obj_buf = buffer;
+	*p_obj_buf_sz = size;
+	return 0;
+}
 }

^ permalink raw reply related	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-12-06  2:07           ` Wangnan (F)
@ 2016-12-06 13:43             ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 73+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-12-06 13:43 UTC (permalink / raw)
  To: Wangnan (F)
  Cc: Arnaldo Carvalho de Melo, Alexei Starovoitov, ast, lizefan,
	hekuang, Ingo Molnar, linux-kernel, pi3orama, joe, Jiri Olsa

Em Tue, Dec 06, 2016 at 10:07:51AM +0800, Wangnan (F) escreveu:
> On 2016/12/6 5:48, Arnaldo Carvalho de Melo wrote:
> > Em Mon, Dec 05, 2016 at 07:02:48PM -0200, Arnaldo Carvalho de Melo escreveu:
> > > Em Mon, Dec 05, 2016 at 08:51:01AM -0800, Alexei Starovoitov escreveu:
> > > > yeah. it's kinda high. I'm guessing rpm llvm libs are in debug mode.
> > > > Try llvm-config --build-mode --assertion-mode
> > > > it should be Release OFF
> > > Probably this was with 3.9 and built from git, quite a while ago, now I
> > > removed it from /usr/local/ and installed what is in f25, but I fear it
> > > will be insufficient, does 3.8 cuts it for what we're testing? Humm, it
> > > looks like it will:

> > > [root@jouet ~]# llc --version
> > > LLVM (http://llvm.org/):
> > >    LLVM version 3.8.0

> > > But I'm now running the container based tests to send a pull req, will
> > > check later, after that.
> > Not really, Wang, we need to update that feature detection test to state what
> > is the minimum required LLVM/clang version, one that has those functions,
> > which, unfortunately, isn't the one in the latest fedora, fedora 25:
 
> I'll set the minimum required LLVM version to 3.9, and report
> warning when LLVM is too old. However, since LLVM interface is
> keep changing, finally we will have problem if we want to support
> 2 or 3 different clang/LLVM. We should keep moving minimum
> requirement LLVM version if we don't want to see '#ifdef's
> spread in our code.

If this area is in that much flux, I see no problem in us both not
enabling this by default, which is the case right now, and go on moving
the minimum required version for LLVM/clang, hopefully at some point
this will get stable and widely available (as in what distros ship),
when we then switch to doing the feature detection automatically.

I see you already submitted the patch to do this test, thanks, will
check and continue processing your series.

- Arnaldo

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-12-05 16:51     ` Alexei Starovoitov
  2016-12-05 21:02       ` Arnaldo Carvalho de Melo
@ 2016-12-06 19:19       ` Arnaldo Carvalho de Melo
  2016-12-06 21:02         ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 73+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-12-06 19:19 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Arnaldo Carvalho de Melo, Wang Nan, ast, lizefan, hekuang,
	Ingo Molnar, linux-kernel, pi3orama, joe, Jiri Olsa

Em Mon, Dec 05, 2016 at 08:51:01AM -0800, Alexei Starovoitov escreveu:
> On Fri, Dec 02, 2016 at 01:44:40PM -0200, Arnaldo Carvalho de Melo wrote:
> > Em Sat, Nov 26, 2016 at 07:03:34AM +0000, Wang Nan escreveu:
> > > Add basic clang support in clang.cpp and test__clang() testcase. The
> > > first testcase checks if builtin clang is able to generate LLVM IR.
> > > 
> > > tests/clang.c is a proxy. Real testcase resides in
> > > utils/c++/clang-test.cpp in c++ and exports C interface to perf test
> > > subsystem.
> > > 
> > > Test result:
> > > 
> > >    $ perf test -v clang
> > >    51: Test builtin clang support                               :
> > >    51.1: Test builtin clang compile C source to IR              :
> > >    --- start ---
> > >    test child forked, pid 13215
> > >    test child finished with 0
> > >    ---- end ----
> > >    Test builtin clang support subtest 0: Ok
> > 
> > While testing this I noticed that the perf binary got huge, can't this
> > be done in some other way, i.e. using dynamic library?
> > 
> > [root@jouet ~]# size /tmp/perf
> >    text	   data	    bss	    dec	    hex	filename
> > 75333688	1421584	23962176	100717448	600d388 /tmp/perf
> > [root@jouet ~]#
> > 
> > I've built it with this:
> > 
> >   make LIBCLANGLLVM=1 O=/tmp/build/perf -C tools/perf install-bin
> > 
> > the resulting binary:
> > 
> > [acme@jouet linux]$ 
> > [acme@jouet linux]$ ls -la ~/bin/perf
> > -rwxr-xr-x. 2 acme acme 131689136 Dec  2 12:31 /home/acme/bin/perf
> > [acme@jouet linux]$ ls -lah ~/bin/perf
> > -rwxr-xr-x. 2 acme acme 126M Dec  2 12:31 /home/acme/bin/perf
> > [acme@jouet linux]$
> > 
> > Huge, after stripping it:
> > 
> > [acme@jouet linux]$ ls -la /tmp/perf
> > -rwxr-xr-x. 1 root root 76759056 Dec  2 12:33 /tmp/perf
> > [acme@jouet linux]$ ls -lah /tmp/perf
> > -rwxr-xr-x. 1 root root 74M Dec  2 12:33 /tmp/perf
> > [acme@jouet linux]$
> > 
> > Still huge :-\
> 
> yeah. it's kinda high. I'm guessing rpm llvm libs are in debug mode.
> Try llvm-config --build-mode --assertion-mode
> it should be Release OFF

It was ON, rebuilding it with

$ cmake -DCMAKE_BUILD_TYPE=Release /home/acme/git/llvm
$ make -j4

Will take a (another) while :-)

- Arnaldo
 
> > But being a n00b on llvm/clang libraries, etc, my question goes back to:
> > can we have this using a libllvm.so or libclang.so dynamic libraries?
> 
> that can also work. The reason we build iovisor/bcc into single binary
> is to ease operational headache.

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-12-06 19:19       ` Arnaldo Carvalho de Melo
@ 2016-12-06 21:02         ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 73+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-12-06 21:02 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Arnaldo Carvalho de Melo, Wang Nan, ast, lizefan, hekuang,
	Ingo Molnar, linux-kernel, pi3orama, joe, Jiri Olsa

Em Tue, Dec 06, 2016 at 04:19:34PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Mon, Dec 05, 2016 at 08:51:01AM -0800, Alexei Starovoitov escreveu:
> > On Fri, Dec 02, 2016 at 01:44:40PM -0200, Arnaldo Carvalho de Melo wrote:
> > >   make LIBCLANGLLVM=1 O=/tmp/build/perf -C tools/perf install-bin
> > > 
> > > the resulting binary:
> > > 
> > > [acme@jouet linux]$ 
> > > [acme@jouet linux]$ ls -la ~/bin/perf
> > > -rwxr-xr-x. 2 acme acme 131689136 Dec  2 12:31 /home/acme/bin/perf
> > > [acme@jouet linux]$ ls -lah ~/bin/perf
> > > -rwxr-xr-x. 2 acme acme 126M Dec  2 12:31 /home/acme/bin/perf
> > > [acme@jouet linux]$
> > > 
> > > Huge, after stripping it:
> > > 
> > > [acme@jouet linux]$ ls -la /tmp/perf
> > > -rwxr-xr-x. 1 root root 76759056 Dec  2 12:33 /tmp/perf
> > > [acme@jouet linux]$ ls -lah /tmp/perf
> > > -rwxr-xr-x. 1 root root 74M Dec  2 12:33 /tmp/perf
> > > [acme@jouet linux]$
> > > 
> > > Still huge :-\
> > 
> > yeah. it's kinda high. I'm guessing rpm llvm libs are in debug mode.
> > Try llvm-config --build-mode --assertion-mode
> > it should be Release OFF
> 
> It was ON, rebuilding it with
> 
> $ cmake -DCMAKE_BUILD_TYPE=Release /home/acme/git/llvm
> $ make -j4
> 
> Will take a (another) while :-)

Almost halved the size:

[acme@jouet build]$ llvm-config --build-mode --assertion-mode
Release
OFF
[acme@jouet build]$ clang -v
clang version 4.0.0 (http://llvm.org/git/clang.git b7a0d79a6691813bf7d6ade1b4e8b21fd502f50a) (http://llvm.org/git/llvm.git 3a783f8716bfc621355e8ae61daf3a2093c341fc)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/6.2.1
Selected GCC installation: /usr/lib/gcc/x86_64-redhat-linux/6.2.1
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
[acme@jouet build]$ llvm-config --version
4.0.0svn
[acme@jouet build]$

[acme@jouet linux]$ ls -la /tmp/perf
-rwxr-xr-x. 1 acme acme 63641016 Dec  6 17:58 /tmp/perf
[acme@jouet linux]$ size /tmp/perf
   text	   data	    bss	    dec	    hex	filename
40877921	1577232	24065712	66520865	3f70721
/tmp/perf
[acme@jouet linux]$ strip /tmp/perf
[acme@jouet linux]$ ls -la /tmp/perf
-rwxr-xr-x. 1 acme acme 42460904 Dec  6 17:58 /tmp/perf
[acme@jouet linux]$ ls -lah /tmp/perf
-rwxr-xr-x. 1 acme acme 41M Dec  6 17:58 /tmp/perf
[acme@jouet linux]$ size /tmp/perf
   text	   data	    bss	    dec	    hex	filename
40877921	1577232	24065712	66520865	3f70721
/tmp/perf
[acme@jouet linux]$ 

^ permalink raw reply	[flat|nested] 73+ messages in thread

* Re: [PATCH v3 10/30] perf clang: Add builtin clang support ant test case
  2016-12-05  4:41       ` Wangnan (F)
@ 2017-01-17 13:38         ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 73+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-01-17 13:38 UTC (permalink / raw)
  To: Wangnan (F)
  Cc: Arnaldo Carvalho de Melo, ast, lizefan, hekuang, Ingo Molnar,
	linux-kernel, pi3orama, joe, Jiri Olsa

Em Mon, Dec 05, 2016 at 12:41:03PM +0800, Wangnan (F) escreveu:
> On 2016/12/5 10:36, Wangnan (F) wrote:
> > On 2016/12/2 23:44, Arnaldo Carvalho de Melo wrote:
> > > Em Sat, Nov 26, 2016 at 07:03:34AM +0000, Wang Nan escreveu:
> > I intentionally use statically linking because it is good for
> > smartphone: we can simply 'adb push' a statically linked perf
> > to Android.

So I'm trying to get back to this, and built -DBUILD_SHARED_LIBS=ON HEAD
llvm/clang, applied your patch to switch from .a to .so and got a smaller perf
binary that is dinamically linked to tons of libraries from LLVM and clang, see
below, how to proceed?

I think we should default to linking it dinamically, which is what I'll have in
a test branch and add some machinery to autodetect and use the right approach,
can you do that while I try to go on processing the next patches?

Its a huge bump in the number of libraries in such a build:

[acme@jouet linux]$ ldd /tmp/perf  | wc -l
174
[acme@jouet linux]$ ldd /tmp/perf | egrep -i llvm\|clang | wc -l
145
[acme@jouet linux]$ 

But one expected by those explicitely enabling support for eBPF, right? Those
needing a llvm/clang toolchain installed can opt for using the external
toolchain, that we keep in place, those with a need for those libraries can use
this approach and then those just wanting perf+eBPF, say on a smartphone, like
you said, can get everything in a static build.

- Arnaldo

[acme@jouet linux]$ ls -lah /tmp/perf
-rwxr-xr-x. 1 acme acme 4.4M Jan 17 10:29 /tmp/perf
[acme@jouet linux]$ size /tmp/perf
   text	   data	    bss	    dec	    hex	filename
3954488	 622440	23912104	28489032	1b2b548	/tmp/perf
[acme@jouet linux]$ ldd /tmp/perf | egrep -i llvm\|clang
	libclangAST.so.40 => /usr/local/lib/libclangAST.so.40 (0x00007f4964981000)
	libclangBasic.so.40 => /usr/local/lib/libclangBasic.so.40 (0x00007f49644e6000)
	libclangCodeGen.so.40 => /usr/local/lib/libclangCodeGen.so.40 (0x00007f4963f92000)
	libclangDriver.so.40 => /usr/local/lib/libclangDriver.so.40 (0x00007f4963c59000)
	libclangFrontend.so.40 => /usr/local/lib/libclangFrontend.so.40 (0x00007f4963945000)
	libclangLex.so.40 => /usr/local/lib/libclangLex.so.40 (0x00007f496368d000)
	libclangTooling.so.40 => /usr/local/lib/libclangTooling.so.40 (0x00007f4963447000)
	libclangEdit.so.40 => /usr/local/lib/libclangEdit.so.40 (0x00007f4963239000)
	libclangSema.so.40 => /usr/local/lib/libclangSema.so.40 (0x00007f4962a32000)
	libclangAnalysis.so.40 => /usr/local/lib/libclangAnalysis.so.40 (0x00007f496279b000)
	libclangParse.so.40 => /usr/local/lib/libclangParse.so.40 (0x00007f49624b4000)
	libclangSerialization.so.40 => /usr/local/lib/libclangSerialization.so.40 (0x00007f4962156000)
	libLLVMLTO.so.40 => /usr/local/lib/libLLVMLTO.so.40 (0x00007f4961f13000)
	libLLVMPasses.so.40 => /usr/local/lib/libLLVMPasses.so.40 (0x00007f4961c6d000)
	libLLVMObjCARCOpts.so.40 => /usr/local/lib/libLLVMObjCARCOpts.so.40 (0x00007f4961a48000)
	libLLVMMIRParser.so.40 => /usr/local/lib/libLLVMMIRParser.so.40 (0x00007f496181d000)
	libLLVMSymbolize.so.40 => /usr/local/lib/libLLVMSymbolize.so.40 (0x00007f496160e000)
	libLLVMDebugInfoPDB.so.40 => /usr/local/lib/libLLVMDebugInfoPDB.so.40 (0x00007f49613ca000)
	libLLVMDebugInfoDWARF.so.40 => /usr/local/lib/libLLVMDebugInfoDWARF.so.40 (0x00007f496118f000)
	libLLVMCoverage.so.40 => /usr/local/lib/libLLVMCoverage.so.40 (0x00007f4960f6d000)
	libLLVMTableGen.so.40 => /usr/local/lib/libLLVMTableGen.so.40 (0x00007f4960d22000)
	libLLVMOrcJIT.so.40 => /usr/local/lib/libLLVMOrcJIT.so.40 (0x00007f4960aea000)
	libLLVMXCoreDisassembler.so.40 => /usr/local/lib/libLLVMXCoreDisassembler.so.40 (0x00007f49608e4000)
	libLLVMXCoreCodeGen.so.40 => /usr/local/lib/libLLVMXCoreCodeGen.so.40 (0x00007f4960697000)
	libLLVMXCoreDesc.so.40 => /usr/local/lib/libLLVMXCoreDesc.so.40 (0x00007f4960489000)
	libLLVMXCoreInfo.so.40 => /usr/local/lib/libLLVMXCoreInfo.so.40 (0x00007f4960287000)
	libLLVMXCoreAsmPrinter.so.40 => /usr/local/lib/libLLVMXCoreAsmPrinter.so.40 (0x00007f4960081000)
	libLLVMSystemZDisassembler.so.40 => /usr/local/lib/libLLVMSystemZDisassembler.so.40 (0x00007f495fe70000)
	libLLVMSystemZCodeGen.so.40 => /usr/local/lib/libLLVMSystemZCodeGen.so.40 (0x00007f495fbde000)
	libLLVMSystemZAsmParser.so.40 => /usr/local/lib/libLLVMSystemZAsmParser.so.40 (0x00007f495f9c6000)
	libLLVMSystemZDesc.so.40 => /usr/local/lib/libLLVMSystemZDesc.so.40 (0x00007f495f767000)
	libLLVMSystemZInfo.so.40 => /usr/local/lib/libLLVMSystemZInfo.so.40 (0x00007f495f565000)
	libLLVMSystemZAsmPrinter.so.40 => /usr/local/lib/libLLVMSystemZAsmPrinter.so.40 (0x00007f495f356000)
	libLLVMSparcDisassembler.so.40 => /usr/local/lib/libLLVMSparcDisassembler.so.40 (0x00007f495f14f000)
	libLLVMSparcCodeGen.so.40 => /usr/local/lib/libLLVMSparcCodeGen.so.40 (0x00007f495ef02000)
	libLLVMSparcAsmParser.so.40 => /usr/local/lib/libLLVMSparcAsmParser.so.40 (0x00007f495ecf0000)
	libLLVMSparcDesc.so.40 => /usr/local/lib/libLLVMSparcDesc.so.40 (0x00007f495eacb000)
	libLLVMSparcInfo.so.40 => /usr/local/lib/libLLVMSparcInfo.so.40 (0x00007f495e8c9000)
	libLLVMSparcAsmPrinter.so.40 => /usr/local/lib/libLLVMSparcAsmPrinter.so.40 (0x00007f495e6ad000)
	libLLVMRISCVDesc.so.40 => /usr/local/lib/libLLVMRISCVDesc.so.40 (0x00007f495e4a5000)
	libLLVMRISCVCodeGen.so.40 => /usr/local/lib/libLLVMRISCVCodeGen.so.40 (0x00007f495e2a2000)
	libLLVMRISCVInfo.so.40 => /usr/local/lib/libLLVMRISCVInfo.so.40 (0x00007f495e0a0000)
	libLLVMPowerPCDisassembler.so.40 => /usr/local/lib/libLLVMPowerPCDisassembler.so.40 (0x00007f495de94000)
	libLLVMPowerPCCodeGen.so.40 => /usr/local/lib/libLLVMPowerPCCodeGen.so.40 (0x00007f495db82000)
	libLLVMPowerPCAsmParser.so.40 => /usr/local/lib/libLLVMPowerPCAsmParser.so.40 (0x00007f495d962000)
	libLLVMPowerPCDesc.so.40 => /usr/local/lib/libLLVMPowerPCDesc.so.40 (0x00007f495d6f9000)
	libLLVMPowerPCInfo.so.40 => /usr/local/lib/libLLVMPowerPCInfo.so.40 (0x00007f495d4f6000)
	libLLVMPowerPCAsmPrinter.so.40 => /usr/local/lib/libLLVMPowerPCAsmPrinter.so.40 (0x00007f495d2db000)
	libLLVMNVPTXCodeGen.so.40 => /usr/local/lib/libLLVMNVPTXCodeGen.so.40 (0x00007f495d03b000)
	libLLVMNVPTXDesc.so.40 => /usr/local/lib/libLLVMNVPTXDesc.so.40 (0x00007f495cde7000)
	libLLVMNVPTXInfo.so.40 => /usr/local/lib/libLLVMNVPTXInfo.so.40 (0x00007f495cbe3000)
	libLLVMNVPTXAsmPrinter.so.40 => /usr/local/lib/libLLVMNVPTXAsmPrinter.so.40 (0x00007f495c9ca000)
	libLLVMMSP430CodeGen.so.40 => /usr/local/lib/libLLVMMSP430CodeGen.so.40 (0x00007f495c79d000)
	libLLVMMSP430Desc.so.40 => /usr/local/lib/libLLVMMSP430Desc.so.40 (0x00007f495c592000)
	libLLVMMSP430Info.so.40 => /usr/local/lib/libLLVMMSP430Info.so.40 (0x00007f495c390000)
	libLLVMMSP430AsmPrinter.so.40 => /usr/local/lib/libLLVMMSP430AsmPrinter.so.40 (0x00007f495c18c000)
	libLLVMMipsDisassembler.so.40 => /usr/local/lib/libLLVMMipsDisassembler.so.40 (0x00007f495bf73000)
	libLLVMMipsCodeGen.so.40 => /usr/local/lib/libLLVMMipsCodeGen.so.40 (0x00007f495bc88000)
	libLLVMMipsAsmParser.so.40 => /usr/local/lib/libLLVMMipsAsmParser.so.40 (0x00007f495ba4a000)
	libLLVMMipsDesc.so.40 => /usr/local/lib/libLLVMMipsDesc.so.40 (0x00007f495b7bf000)
	libLLVMMipsInfo.so.40 => /usr/local/lib/libLLVMMipsInfo.so.40 (0x00007f495b5bc000)
	libLLVMMipsAsmPrinter.so.40 => /usr/local/lib/libLLVMMipsAsmPrinter.so.40 (0x00007f495b3ad000)
	libLLVMLanaiDisassembler.so.40 => /usr/local/lib/libLLVMLanaiDisassembler.so.40 (0x00007f495b1a7000)
	libLLVMLanaiCodeGen.so.40 => /usr/local/lib/libLLVMLanaiCodeGen.so.40 (0x00007f495af64000)
	libLLVMLanaiAsmParser.so.40 => /usr/local/lib/libLLVMLanaiAsmParser.so.40 (0x00007f495ad58000)
	libLLVMLanaiDesc.so.40 => /usr/local/lib/libLLVMLanaiDesc.so.40 (0x00007f495ab4a000)
	libLLVMLanaiInstPrinter.so.40 => /usr/local/lib/libLLVMLanaiInstPrinter.so.40 (0x00007f495a943000)
	libLLVMLanaiInfo.so.40 => /usr/local/lib/libLLVMLanaiInfo.so.40 (0x00007f495a741000)
	libLLVMHexagonDisassembler.so.40 => /usr/local/lib/libLLVMHexagonDisassembler.so.40 (0x00007f495a526000)
	libLLVMHexagonCodeGen.so.40 => /usr/local/lib/libLLVMHexagonCodeGen.so.40 (0x00007f495a15e000)
	libLLVMHexagonAsmParser.so.40 => /usr/local/lib/libLLVMHexagonAsmParser.so.40 (0x00007f4959f23000)
	libLLVMHexagonDesc.so.40 => /usr/local/lib/libLLVMHexagonDesc.so.40 (0x00007f4959c77000)
	libLLVMHexagonInfo.so.40 => /usr/local/lib/libLLVMHexagonInfo.so.40 (0x00007f4959a75000)
	libLLVMBPFDisassembler.so.40 => /usr/local/lib/libLLVMBPFDisassembler.so.40 (0x00007f4959871000)
	libLLVMBPFCodeGen.so.40 => /usr/local/lib/libLLVMBPFCodeGen.so.40 (0x00007f4959651000)
	libLLVMBPFDesc.so.40 => /usr/local/lib/libLLVMBPFDesc.so.40 (0x00007f4959447000)
	libLLVMBPFInfo.so.40 => /usr/local/lib/libLLVMBPFInfo.so.40 (0x00007f4959244000)
	libLLVMBPFAsmPrinter.so.40 => /usr/local/lib/libLLVMBPFAsmPrinter.so.40 (0x00007f4959040000)
	libLLVMARMDisassembler.so.40 => /usr/local/lib/libLLVMARMDisassembler.so.40 (0x00007f4958e0c000)
	libLLVMARMCodeGen.so.40 => /usr/local/lib/libLLVMARMCodeGen.so.40 (0x00007f4958a8a000)
	libLLVMARMAsmParser.so.40 => /usr/local/lib/libLLVMARMAsmParser.so.40 (0x00007f495880d000)
	libLLVMARMDesc.so.40 => /usr/local/lib/libLLVMARMDesc.so.40 (0x00007f4958533000)
	libLLVMARMInfo.so.40 => /usr/local/lib/libLLVMARMInfo.so.40 (0x00007f4958330000)
	libLLVMARMAsmPrinter.so.40 => /usr/local/lib/libLLVMARMAsmPrinter.so.40 (0x00007f4958111000)
	libLLVMAMDGPUDisassembler.so.40 => /usr/local/lib/libLLVMAMDGPUDisassembler.so.40 (0x00007f4957ef2000)
	libLLVMAMDGPUCodeGen.so.40 => /usr/local/lib/libLLVMAMDGPUCodeGen.so.40 (0x00007f4957b91000)
	libLLVMAMDGPUAsmParser.so.40 => /usr/local/lib/libLLVMAMDGPUAsmParser.so.40 (0x00007f4957922000)
	libLLVMAMDGPUDesc.so.40 => /usr/local/lib/libLLVMAMDGPUDesc.so.40 (0x00007f49575c8000)
	libLLVMAMDGPUInfo.so.40 => /usr/local/lib/libLLVMAMDGPUInfo.so.40 (0x00007f49573c6000)
	libLLVMAMDGPUAsmPrinter.so.40 => /usr/local/lib/libLLVMAMDGPUAsmPrinter.so.40 (0x00007f4957195000)
	libLLVMAMDGPUUtils.so.40 => /usr/local/lib/libLLVMAMDGPUUtils.so.40 (0x00007f4956f79000)
	libLLVMAArch64Disassembler.so.40 => /usr/local/lib/libLLVMAArch64Disassembler.so.40 (0x00007f4956d58000)
	libLLVMAArch64CodeGen.so.40 => /usr/local/lib/libLLVMAArch64CodeGen.so.40 (0x00007f4956a18000)
	libLLVMAArch64AsmParser.so.40 => /usr/local/lib/libLLVMAArch64AsmParser.so.40 (0x00007f49567b9000)
	libLLVMAArch64Desc.so.40 => /usr/local/lib/libLLVMAArch64Desc.so.40 (0x00007f495651d000)
	libLLVMAArch64Info.so.40 => /usr/local/lib/libLLVMAArch64Info.so.40 (0x00007f495631a000)
	libLLVMAArch64AsmPrinter.so.40 => /usr/local/lib/libLLVMAArch64AsmPrinter.so.40 (0x00007f49560bb000)
	libLLVMAArch64Utils.so.40 => /usr/local/lib/libLLVMAArch64Utils.so.40 (0x00007f4955e9c000)
	libLLVMObjectYAML.so.40 => /usr/local/lib/libLLVMObjectYAML.so.40 (0x00007f4955c5d000)
	libLLVMLibDriver.so.40 => /usr/local/lib/libLLVMLibDriver.so.40 (0x00007f4955a57000)
	libLLVMOption.so.40 => /usr/local/lib/libLLVMOption.so.40 (0x00007f4955849000)
	libLLVMX86Disassembler.so.40 => /usr/local/lib/libLLVMX86Disassembler.so.40 (0x00007f49554e6000)
	libLLVMX86AsmParser.so.40 => /usr/local/lib/libLLVMX86AsmParser.so.40 (0x00007f495523e000)
	libLLVMX86CodeGen.so.40 => /usr/local/lib/libLLVMX86CodeGen.so.40 (0x00007f4954dc9000)
	libLLVMGlobalISel.so.40 => /usr/local/lib/libLLVMGlobalISel.so.40 (0x00007f4954bc5000)
	libLLVMSelectionDAG.so.40 => /usr/local/lib/libLLVMSelectionDAG.so.40 (0x00007f4954799000)
	libLLVMAsmPrinter.so.40 => /usr/local/lib/libLLVMAsmPrinter.so.40 (0x00007f49544ff000)
	libLLVMDebugInfoCodeView.so.40 => /usr/local/lib/libLLVMDebugInfoCodeView.so.40 (0x00007f495429b000)
	libLLVMDebugInfoMSF.so.40 => /usr/local/lib/libLLVMDebugInfoMSF.so.40 (0x00007f495408c000)
	libLLVMX86Desc.so.40 => /usr/local/lib/libLLVMX86Desc.so.40 (0x00007f4953ca8000)
	libLLVMMCDisassembler.so.40 => /usr/local/lib/libLLVMMCDisassembler.so.40 (0x00007f4953a9f000)
	libLLVMX86Info.so.40 => /usr/local/lib/libLLVMX86Info.so.40 (0x00007f495389d000)
	libLLVMX86AsmPrinter.so.40 => /usr/local/lib/libLLVMX86AsmPrinter.so.40 (0x00007f4953648000)
	libLLVMX86Utils.so.40 => /usr/local/lib/libLLVMX86Utils.so.40 (0x00007f495343c000)
	libLLVMMCJIT.so.40 => /usr/local/lib/libLLVMMCJIT.so.40 (0x00007f495322e000)
	libLLVMLineEditor.so.40 => /usr/local/lib/libLLVMLineEditor.so.40 (0x00007f495302a000)
	libLLVMInterpreter.so.40 => /usr/local/lib/libLLVMInterpreter.so.40 (0x00007f4952e03000)
	libLLVMExecutionEngine.so.40 => /usr/local/lib/libLLVMExecutionEngine.so.40 (0x00007f4952be2000)
	libLLVMRuntimeDyld.so.40 => /usr/local/lib/libLLVMRuntimeDyld.so.40 (0x00007f4952991000)
	libLLVMCodeGen.so.40 => /usr/local/lib/libLLVMCodeGen.so.40 (0x00007f4952407000)
	libLLVMTarget.so.40 => /usr/local/lib/libLLVMTarget.so.40 (0x00007f49521fb000)
	libLLVMCoroutines.so.40 => /usr/local/lib/libLLVMCoroutines.so.40 (0x00007f4951fdd000)
	libLLVMipo.so.40 => /usr/local/lib/libLLVMipo.so.40 (0x00007f4951d0d000)
	libLLVMInstrumentation.so.40 => /usr/local/lib/libLLVMInstrumentation.so.40 (0x00007f4951a70000)
	libLLVMVectorize.so.40 => /usr/local/lib/libLLVMVectorize.so.40 (0x00007f49517ea000)
	libLLVMScalarOpts.so.40 => /usr/local/lib/libLLVMScalarOpts.so.40 (0x00007f49513d3000)
	libLLVMLinker.so.40 => /usr/local/lib/libLLVMLinker.so.40 (0x00007f49511b7000)
	libLLVMIRReader.so.40 => /usr/local/lib/libLLVMIRReader.so.40 (0x00007f4950fb0000)
	libLLVMAsmParser.so.40 => /usr/local/lib/libLLVMAsmParser.so.40 (0x00007f4950d59000)
	libLLVMInstCombine.so.40 => /usr/local/lib/libLLVMInstCombine.so.40 (0x00007f4950a8b000)
	libLLVMTransformUtils.so.40 => /usr/local/lib/libLLVMTransformUtils.so.40 (0x00007f4950733000)
	libLLVMBitWriter.so.40 => /usr/local/lib/libLLVMBitWriter.so.40 (0x00007f49504fe000)
	libLLVMAnalysis.so.40 => /usr/local/lib/libLLVMAnalysis.so.40 (0x00007f495005b000)
	libLLVMObject.so.40 => /usr/local/lib/libLLVMObject.so.40 (0x00007f494fde8000)
	libLLVMMCParser.so.40 => /usr/local/lib/libLLVMMCParser.so.40 (0x00007f494fbac000)
	libLLVMMC.so.40 => /usr/local/lib/libLLVMMC.so.40 (0x00007f494f919000)
	libLLVMBitReader.so.40 => /usr/local/lib/libLLVMBitReader.so.40 (0x00007f494f6cd000)
	libLLVMProfileData.so.40 => /usr/local/lib/libLLVMProfileData.so.40 (0x00007f494f498000)
	libLLVMCore.so.40 => /usr/local/lib/libLLVMCore.so.40 (0x00007f494f049000)
	libLLVMSupport.so.40 => /usr/local/lib/libLLVMSupport.so.40 (0x00007f494ed49000)
	libLLVMDemangle.so.40 => /usr/local/lib/libLLVMDemangle.so.40 (0x00007f494eb30000)
	libclangASTMatchers.so.40 => /usr/local/lib/../lib/libclangASTMatchers.so.40 (0x00007f494daf9000)
	libclangFormat.so.40 => /usr/local/lib/../lib/libclangFormat.so.40 (0x00007f494d88f000)
	libclangRewrite.so.40 => /usr/local/lib/../lib/libclangRewrite.so.40 (0x00007f494d67e000)
	libclangToolingCore.so.40 => /usr/local/lib/../lib/libclangToolingCore.so.40 (0x00007f494d46d000)
[acme@jouet linux]$

> > The resulting ELF executable would be even larger if LLVM is
> > built with default setting.
> > 
> > In my setting the resuling 'perf' is less than 60MB:
> > 
> >  $ ls -s  ~/perf -h
> >  58M /home/wn/perf
> > 
> >  $ size  ~/perf
> >    text       data        bss        dec        hex    filename
> >  56931273    2950808    24108632    83990713    50198b9 /home/wn/perf
> > 
> > It is reasonable for me.
> > 
> > I think using dynamic clang and llvm libraries is possible but I
> > never tried it before. It depend on LLVM compiling. I think if
> > distro provides shared libraries then perf can utilize them
> > automatically. Let me check it today.
> > 
> 
> Good news: it works.
> 
> To enable llvm and clang dynamic libraries, we need to build llvm and clang
> with
> cmake option -DBUILD_SHARED_LIBS=ON. Then apply a trivial patch to perf:
> 
> diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
> index dfb20dd..e3054f3 100644
> --- a/tools/perf/Makefile.perf
> +++ b/tools/perf/Makefile.perf
> @@ -346,7 +346,7 @@ LIBS = -Wl,--whole-archive $(PERFLIBS)
> -Wl,--no-whole-archive -Wl,--start-group
> 
>  ifeq ($(USE_CLANG), 1)
>    CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema
> Analysis Parse Serialization
> -  LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell
> $(LLVM_CONFIG) --libdir)/libclang$(l).a))
> +  LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell
> $(LLVM_CONFIG) --libdir)/libclang$(l).so))
>    LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group
>  endif
> 
> (replace '.a' to '.so')
> 
> Resuling perf executable:
> 
> $ ls -s -h ~/perf
> 26M /home/wn/perf
> 
> $ size ~/perf
>    text       data        bss        dec        hex    filename
> 4274339     755032    23959984    28989355    1ba57ab /home/wn/perf
> 
> $ strip ~/perf
> $ ls -s -h
> 4.9M /home/wn/perf
> 
> $ ldd ~/perf | grep 'LLVM\|clang'
>     libclangBasic.so => /tmp/oxygen_root/usr/lib64/libclangBasic.so
> (0x00007f24da49f000)
>     libclangCodeGen.so => /tmp/oxygen_root/usr/lib64/libclangCodeGen.so
> (0x00007f24d9f72000)
>     libclangFrontend.so => /tmp/oxygen_root/usr/lib64/libclangFrontend.so
> (0x00007f24d9c64000)
>     libclangTooling.so => /tmp/oxygen_root/usr/lib64/libclangTooling.so
> (0x00007f24d9a01000)
>     libLLVMBPFCodeGen.so => /tmp/oxygen_root/usr/lib64/libLLVMBPFCodeGen.so
> (0x00007f24d97e2000)
>     libLLVMBPFDesc.so => /tmp/oxygen_root/usr/lib64/libLLVMBPFDesc.so
> (0x00007f24d95da000)
>     ....
> 
> As I said, if distro provides dynamic libraries then everything would be
> fine.
> 
> If you are okay with the above conclusion, in next version I'll use
> '-lclangBasic'
> style linking options so it works for both dynamic and static LLVM/clang,
> then let's
> wait for distro's action.
> 
> Thank you.

^ permalink raw reply	[flat|nested] 73+ messages in thread

end of thread, other threads:[~2017-01-17 13:49 UTC | newest]

Thread overview: 73+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-26  7:03 [PATCH v3 00/30] perf clang: Builtin clang and perfhook support Wang Nan
2016-11-26  7:03 ` [PATCH v3 01/30] tools lib bpf: Add missing BPF functions Wang Nan
2016-11-26 17:10   ` Alexei Starovoitov
2016-12-02 10:37   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 02/30] tools lib bpf: Add private field for bpf_object Wang Nan
2016-11-26 17:11   ` Alexei Starovoitov
2016-12-02 10:37   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 03/30] tools lib bpf: Retrive bpf_map through offset of bpf_map_def Wang Nan
2016-11-26 17:12   ` Alexei Starovoitov
2016-12-02 10:38   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 04/30] perf tools: Introduce perf hooks Wang Nan
2016-12-02 10:38   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 05/30] perf tools: Pass context to perf hook functions Wang Nan
2016-12-06  8:21   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 06/30] perf llvm: Extract helpers in llvm-utils.c Wang Nan
2016-12-06  8:21   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 07/30] tools build: Add feature detection for LLVM Wang Nan
2016-12-06  8:22   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 08/30] tools build: Add feature detection for clang Wang Nan
2016-12-06  8:22   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 09/30] perf build: Add clang and llvm compile and linking support Wang Nan
2016-12-06  8:23   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 10/30] perf clang: Add builtin clang support ant test case Wang Nan
2016-11-26 17:17   ` Alexei Starovoitov
2016-11-28  7:41     ` Wangnan (F)
2016-12-02 15:44   ` Arnaldo Carvalho de Melo
2016-12-05  2:36     ` Wangnan (F)
2016-12-05  4:41       ` Wangnan (F)
2017-01-17 13:38         ` Arnaldo Carvalho de Melo
2016-12-05 16:51     ` Alexei Starovoitov
2016-12-05 21:02       ` Arnaldo Carvalho de Melo
2016-12-05 21:48         ` Arnaldo Carvalho de Melo
2016-12-06  2:07           ` Wangnan (F)
2016-12-06 13:43             ` Arnaldo Carvalho de Melo
2016-12-06 19:19       ` Arnaldo Carvalho de Melo
2016-12-06 21:02         ` Arnaldo Carvalho de Melo
2016-12-06  8:23   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 11/30] perf clang: Use real file system for #include Wang Nan
2016-12-06  8:24   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 12/30] perf clang: Allow passing CFLAGS to builtin clang Wang Nan
2016-12-06  8:25   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 13/30] perf clang: Update test case to use real BPF script Wang Nan
2016-12-06  8:25   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 14/30] perf clang: Support compile IR to BPF object and add testcase Wang Nan
2016-11-26 17:25   ` Alexei Starovoitov
2016-11-28  6:32     ` Wangnan (F)
2016-11-28 10:31       ` Wangnan (F)
2016-11-28 19:33         ` Alexei Starovoitov
2016-12-06  8:26   ` [tip:perf/core] " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 15/30] perf clang: Compile BPF script use builtin clang support Wang Nan
2016-12-06  8:26   ` [tip:perf/core] perf clang: Compile BPF script using " tip-bot for Wang Nan
2016-11-26  7:03 ` [PATCH v3 16/30] perf clang: Pass full path to builtin clang Wang Nan
2016-11-26  7:03 ` [PATCH v3 17/30] perf clang: Pass CFLAGS " Wang Nan
2016-11-26  7:03 ` [PATCH v3 18/30] perf clang jit: Wrap llvm::Module using PerfModule Wang Nan
2016-11-26  7:03 ` [PATCH v3 19/30] perf clang jit: Insignt BPF and JIT functions in a Module Wang Nan
2016-11-26 17:32   ` Alexei Starovoitov
2016-11-26  7:03 ` [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions Wang Nan
2016-11-26 17:29   ` Alexei Starovoitov
2016-11-28  6:42     ` Wangnan (F)
2016-11-26  7:03 ` [PATCH v3 21/30] perf clang jit: Export functions for jitted code Wang Nan
2016-11-26  7:03 ` [PATCH v3 22/30] perf clang jit: Actually JIT and hook in bpf loader Wang Nan
2016-11-26  7:03 ` [PATCH v3 23/30] perf clang jit: Collect the lowest address in maps section as map_base Wang Nan
2016-11-26  7:03 ` [PATCH v3 24/30] perf clang jit: Retrive fd of BPF map from its offset Wang Nan
2016-11-26  7:03 ` [PATCH v3 25/30] perf clang jit: Allow jitted perf hook access BPF maps Wang Nan
2016-11-26 17:09   ` Alexei Starovoitov
2016-11-26  7:03 ` [PATCH v3 26/30] perf clang: Link BPF functions declaration into perf Wang Nan
2016-11-26 17:40   ` Alexei Starovoitov
2016-11-30 16:12     ` Arnaldo Carvalho de Melo
2016-12-01  1:56       ` [PATCH v3 26/30 - cleanup] " Wang Nan
2016-11-26  7:03 ` [PATCH v3 27/30] perf clang: Declare BPF functions for BPF scripts automatically Wang Nan
2016-11-26  7:03 ` [PATCH v3 28/30] perf clang: Include helpers to BPF scripts Wang Nan
2016-11-26  7:03 ` [PATCH v3 29/30] perf clang builtin: Define hook helpers by default Wang Nan
2016-11-26  7:03 ` [PATCH v3 30/30] perf clang jit: Export getpid() to perf hook Wang Nan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).