Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1522295 > unrolled thread
| Started by | Wang Nan <wangnan0@huawei.com> |
|---|---|
| First post | 2016-11-15 05:10 +0100 |
| Last post | 2016-11-15 05:40 +0100 |
| Articles | 20 on this page of 36 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH 00/34] perf clang: Builtin clang and perfhook support Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:10 +0100
[PATCH 21/34] perf clang: Pass CFLAGS to builtin clang Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:10 +0100
[PATCH 33/34] perf clang builtin: Define hook helpers by default Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:10 +0100
[PATCH 28/34] perf clang jit: Access BPF map Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:10 +0100
[PATCH 16/34] perf clang: Allow passing CFLAGS to builtin clang Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:10 +0100
[PATCH 23/34] perf clang jit: Insignt BPF and JIT functions in a Module Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:10 +0100
[PATCH 02/34] perf record: Fix segfault when running with suid and kptr_restrict is 1 Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:10 +0100
[PATCH 06/34] tools lib bpf: Add private field for bpf_object Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:10 +0100
[PATCH 03/34] tools perf: Add missing struct defeinition in probe_event.h Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 01/34] perf tools: Fix kernel version error in ubuntu Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 24/34] perf clang jit: add PerfModule::doJIT to JIT perfhook functions Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 30/34] perf clang: Link BPF functions declaration into perf Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 11/34] tools build: Add feature detection for LLVM Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 32/34] perf clang: Include helpers to BPF scripts Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 05/34] tools lib bpf: Add missing bpf map functions Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
Re: [PATCH 05/34] tools lib bpf: Add missing bpf map functions "Wangnan (F)" <wangnan0@huawei.com> - 2016-11-17 04:30 +0100
[PATCH 31/34] perf clang: Declare BPF functions for BPF scripts automatically Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 29/34] perf clang jit: Allow jitted perf hook access BPF maps Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 34/34] perf clang git: Export getpid() to perf hook Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 09/34] perf tools: Pass context to perf hook functions Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 22/34] perf clang jit: Wrap llvm::Module using PerfModule Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 25/34] perf clang jit: Export functions for jitted code Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 20/34] perf clang: Pass full path to builtin clang Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 18/34] perf clang: Support compile IR to BPF object and add testcase Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 15/34] perf clang: Use real file system for #include Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 27/34] perf clang jit: Collect the lowest address in maps section as map_base Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 17/34] perf clang: Update test case to use real BPF script Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 13/34] perf build: Add clang and llvm compile and linking support Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 12/34] tools build: Add feature detection for clang Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 08/34] perf tools: Introduce perf hooks Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 07/34] tools lib bpf: Retrive bpf_map through offset of bpf_map_def Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 26/34] perf clang jit: Actually JIT and hook in bpf loader Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 14/34] perf clang: Add builtin clang support ant test case Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 10/34] perf llvm: Extract helpers in llvm-utils.c Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
[PATCH 19/34] perf clang: Compile BPF script use builtin clang support Wang Nan <wangnan0@huawei.com> - 2016-11-15 05:20 +0100
Re: [PATCH 00/34] perf clang: Builtin clang and perfhook support "Wangnan (F)" <wangnan0@huawei.com> - 2016-11-15 05:40 +0100
Page 1 of 2 [1] 2 Next page →
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:10 +0100 |
| Subject | [PATCH 00/34] perf clang: Builtin clang and perfhook support |
| Message-ID | <sDDeh-8kE-3@gated-at.bofh.it> |
This is version 2 of perf builtin clang patch series. Compare to v1,
add an exciting feature: jit compiling perf hook functions. This
features allows script writer report result through BPF map in a
customized way.
At the end of this cover letter lists an example shows how to capture
and report a syscall histogram.
This patchset is based on current perf/core.
In this patchset:
Patch 1 - 4 are bugfixes left in my local tree.
Patch 5 - 7 are preparation in libbpf.
Patch 8 - 9 introduce perf hook to perf.
Patch 10 - 21 are patches support builtin clang. Some of then are already
collected by Arnaldo in tmp.perf/builtin-clang. They are slightly
adjusted in this v2 series.
Patch 22 - 29 add JIT compiling to builting clang and add them to perf hook.
Patch 30 - 34 are easy of use improvements. 1) builtin clang defines macros
and helpers by default using builtin include headers. Default
headers can be turned off by -UBUILTIN_CLANG_DEFAULT_INCLUDE.
2) allow JITted perf hooks access more functions in libc.
Example: build syscall histogram, exclude syscalls issued by perf itself.
Please note following improvements:
1. Don't need define many bpf helpers by hand.
See bpf_map_lookup_elem and bpf_get_current_pid_tgid.
2. See how pid of git is passed to BPF script attached to
raw_syscalls:sys_enter.
$ 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);
jit_helper__map_update_elem(ctx, &GVALS, &key, &perf_pid, 0);
}
SEC("perfhook:record_end")
void record_end(void *ctx)
{
u64 key = -1, value;
while (!jit_helper__map_get_next_key(ctx, &syscall_counter, &key, &key)) {
jit_helper__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 8 count: 6
syscall 11 count: 1
syscall 4 count: 6
syscall 21 count: 1
syscall 5 count: 3
syscall 231 count: 1
syscall 45 count: 3
syscall 0 count: 24
syscall 257 count: 1
syscall 59 count: 4
syscall 23 count: 9
syscall 78 count: 2
syscall 41 count: 4
syscall 72 count: 8
syscall 10 count: 3
syscall 321 count: 1
syscall 298 count: 7
syscall 16 count: 21
syscall 9 count: 16
syscall 1 count: 114
syscall 12 count: 3
syscall 14 count: 35
syscall 158 count: 1
syscall 2 count: 15
syscall 7 count: 18
syscall 3 count: 11
[ perf record: Captured and wrote 0.011 MB perf.data ]
Eric Leblond (1):
tools lib bpf: fix maps resolution
Wang Nan (33):
perf tools: Fix kernel version error in ubuntu
perf record: Fix segfault when running with suid and kptr_restrict is
1
tools perf: Add missing struct defeinition in probe_event.h
tools lib bpf: Add missing bpf map 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: Access BPF map
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 git: 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 | 177 ++++++---
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 | 24 ++
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 | 498 ++++++++++++++++++++++++++
tools/perf/util/c++/clang.h | 61 ++++
tools/perf/util/jit-helpers.c | 60 ++++
tools/perf/util/jit-helpers.h | 30 ++
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/probe-event.h | 2 +
tools/perf/util/symbol.c | 2 +-
tools/perf/util/util-cxx.h | 26 ++
tools/perf/util/util.c | 55 ++-
43 files changed, 1991 insertions(+), 100 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
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
--
2.10.1
[toc] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:10 +0100 |
| Subject | [PATCH 21/34] perf clang: Pass CFLAGS to builtin clang |
| Message-ID | <sDDeh-8kE-7@gated-at.bofh.it> |
| In reply to | #1522295 |
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
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:10 +0100 |
| Subject | [PATCH 33/34] perf clang builtin: Define hook helpers by default |
| Message-ID | <sDDeh-8kE-11@gated-at.bofh.it> |
| In reply to | #1522295 |
Append prototypes of helpers appears in exported_funcs to default include 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++/bpf-helper-str.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/perf/util/c++/bpf-helper-str.c b/tools/perf/util/c++/bpf-helper-str.c index 17f915c..69aca3c 100644 --- a/tools/perf/util/c++/bpf-helper-str.c +++ b/tools/perf/util/c++/bpf-helper-str.c @@ -10,6 +10,14 @@ const char clang_builtin_bpf_helper_str[] = " unsigned int max_entries;\n" "};\n" "#define SEC(NAME) __attribute__((section(NAME), used))\n" +"extern void test__clang_callback(int);\n" +"extern int printf(const char *, ...);\n" +"extern int puts(const char *);\n" +"extern int jit_helper__map_update_elem(void *, void *, void *, void *, unsigned long);\n" +"extern int jit_helper__map_lookup_elem(void *, void *, void *, void *);\n" +"extern int jit_helper__map_get_next_key(void *, void *, void *, void *);\n" +"extern int jit_helper__map_pin(void *, void *, const char *);\n" +"extern int jit_helper__map_get(const char *);\n" "#endif\n" "#endif" ; -- 2.10.1
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:10 +0100 |
| Subject | [PATCH 28/34] perf clang jit: Access BPF map |
| Message-ID | <sDDeh-8kE-9@gated-at.bofh.it> |
| In reply to | #1522295 |
---
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
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:10 +0100 |
| Subject | [PATCH 16/34] perf clang: Allow passing CFLAGS to builtin clang |
| Message-ID | <sDDeh-8kE-15@gated-at.bofh.it> |
| In reply to | #1522295 |
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
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:10 +0100 |
| Subject | [PATCH 23/34] perf clang jit: Insignt BPF and JIT functions in a Module |
| Message-ID | <sDDeh-8kE-13@gated-at.bofh.it> |
| In reply to | #1522295 |
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
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:10 +0100 |
| Subject | [PATCH 02/34] perf record: Fix segfault when running with suid and kptr_restrict is 1 |
| Message-ID | <sDDeh-8kE-17@gated-at.bofh.it> |
| In reply to | #1522295 |
Before this patch perf panic if kptr_restrict set to 1 and perf is owned by root with suid set: $ whoami wangnan $ ls -l ./perf -rwsr-xr-x 1 root root 19781908 Sep 21 19:29 /home/wangnan/perf $ cat /proc/sys/kernel/kptr_restrict 1 $ cat /proc/sys/kernel/perf_event_paranoid -1 $ ./perf record -a Segmentation fault (core dumped) The reason is perf assumes it is allowed to read kptr from /proc/kallsyms when euid is root, but in fact kernel doesn't allow it reading kptr when euid and uid are not match with each other: $ cp /bin/cat . $ sudo chown root:root ./cat $ sudo chmod u+s ./cat $ cat /proc/kallsyms | grep do_fork 0000000000000000 T _do_fork <--- kptr is hidden even euid is root $ sudo cat /proc/kallsyms | grep do_fork ffffffff81080230 T _do_fork See lib/vsprintf.c for kernel side code. This patch fixes this problem by checking both uid and euid. Signed-off-by: Wang Nan <wangnan0@huawei.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/symbol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index aecff69..420ada9 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1962,7 +1962,7 @@ static bool symbol__read_kptr_restrict(void) char line[8]; if (fgets(line, sizeof(line), fp) != NULL) - value = (geteuid() != 0) ? + value = ((geteuid() != 0) || (getuid() != 0)) ? (atoi(line) != 0) : (atoi(line) == 2); -- 2.10.1
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:10 +0100 |
| Subject | [PATCH 06/34] tools lib bpf: Add private field for bpf_object |
| Message-ID | <sDDei-8kE-19@gated-at.bofh.it> |
| In reply to | #1522295 |
Like other classes defined in libbpf.h (like 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
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:20 +0100 |
| Subject | [PATCH 03/34] tools perf: Add missing struct defeinition in probe_event.h |
| Message-ID | <sDDnY-8py-9@gated-at.bofh.it> |
| In reply to | #1522295 |
Commit 0b3c2264ae30 ("perf symbols: Fix kallsyms perf test on ppc64le")
referes struct symbol in probe_event.h, but forget include its definition.
Gcc will complain for it.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/probe-event.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 8091d15..5d4e940 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -18,6 +18,8 @@ struct probe_conf {
extern struct probe_conf probe_conf;
extern bool probe_event_dry_run;
+struct symbol;
+
/* kprobe-tracer and uprobe-tracer tracing point */
struct probe_trace_point {
char *realname; /* function real name (if needed) */
--
2.10.1
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:20 +0100 |
| Subject | [PATCH 01/34] perf tools: Fix kernel version error in ubuntu |
| Message-ID | <sDDnX-8py-1@gated-at.bofh.it> |
| In reply to | #1522295 |
On ubuntu the internal kernel version code is different from what can
be retrived from uname:
$ uname -r
4.4.0-47-generic
$ cat /lib/modules/`uname -r`/build/include/generated/uapi/linux/version.h
#define LINUX_VERSION_CODE 263192
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
$ cat /lib/modules/`uname -r`/build/include/generated/utsrelease.h
#define UTS_RELEASE "4.4.0-47-generic"
#define UTS_UBUNTU_RELEASE_ABI 47
$ cat /proc/version_signature
Ubuntu 4.4.0-47.68-generic 4.4.24
The macro LINUX_VERSION_CODE is set to 4.4.24 (263192 == 0x40418), but
`uname -r` reports 4.4.0.
This mismatch causes LINUX_VERSION_CODE macro passed to BPF script become
an incorrect value, results in magic failure in BPF loading:
$ sudo ./buildperf/perf record -e ./tools/perf/tests/bpf-script-example.c ls
event syntax error: './tools/perf/tests/bpf-script-example.c'
\___ Failed to load program for unknown reason
According to Ubuntu document (https://wiki.ubuntu.com/Kernel/FAQ), the
correct kernel version can be retrived through /proc/version_signature, which
is ubuntu specific.
This patch checks the existance of /proc/version_signature, and returns
version number through parsing this file instead of uname. Version string
is untouched (value returns from uname) because `uname -r` is required
to be consistence with path of kbuild directory in /lib/module.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/util.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 53 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 5bbd1f6..67ac765 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -637,12 +637,63 @@ bool find_process(const char *name)
return ret ? false : true;
}
+static int
+fetch_ubuntu_kernel_version(unsigned int *puint)
+{
+ ssize_t len;
+ size_t line_len = 0;
+ char *ptr, *line = NULL;
+ int version, patchlevel, sublevel, err;
+ FILE *vsig = fopen("/proc/version_signature", "r");
+
+ if (!vsig) {
+ pr_debug("Open /proc/version_signature failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+ len = getline(&line, &line_len, vsig);
+ fclose(vsig);
+ err = -1;
+ if (len <= 0) {
+ pr_debug("Reading from /proc/version_signature failed: %s\n",
+ strerror(errno));
+ goto errout;
+ }
+
+ ptr = strrchr(line, ' ');
+ if (!ptr) {
+ pr_debug("Parsing /proc/version_signature failed: %s\n", line);
+ goto errout;
+ }
+
+ err = sscanf(ptr + 1, "%d.%d.%d",
+ &version, &patchlevel, &sublevel);
+ if (err != 3) {
+ pr_debug("Unable to get kernel version from /proc/version_signature '%s'\n",
+ line);
+ goto errout;
+ }
+
+ if (puint)
+ *puint = (version << 16) + (patchlevel << 8) + sublevel;
+ err = 0;
+errout:
+ free(line);
+ return err;
+}
+
int
fetch_kernel_version(unsigned int *puint, char *str,
size_t str_size)
{
struct utsname utsname;
int version, patchlevel, sublevel, err;
+ bool int_ver_ready = false;
+
+ if (access("/proc/version_signature", R_OK) == 0)
+ if (!fetch_ubuntu_kernel_version(puint))
+ int_ver_ready = true;
if (uname(&utsname))
return -1;
@@ -656,12 +707,12 @@ fetch_kernel_version(unsigned int *puint, char *str,
&version, &patchlevel, &sublevel);
if (err != 3) {
- pr_debug("Unablt to get kernel version from uname '%s'\n",
+ pr_debug("Unable to get kernel version from uname '%s'\n",
utsname.release);
return -1;
}
- if (puint)
+ if (puint && !int_ver_ready)
*puint = (version << 16) + (patchlevel << 8) + sublevel;
return 0;
}
--
2.10.1
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:20 +0100 |
| Subject | [PATCH 24/34] perf clang jit: add PerfModule::doJIT to JIT perfhook functions |
| Message-ID | <sDDnX-8py-3@gated-at.bofh.it> |
| In reply to | #1522295 |
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
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:20 +0100 |
| Subject | [PATCH 30/34] perf clang: Link BPF functions declaration into perf |
| Message-ID | <sDDnY-8py-7@gated-at.bofh.it> |
| In reply to | #1522295 |
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
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:20 +0100 |
| Subject | [PATCH 11/34] tools build: Add feature detection for LLVM |
| Message-ID | <sDDnY-8py-21@gated-at.bofh.it> |
| In reply to | #1522295 |
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
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:20 +0100 |
| Subject | [PATCH 32/34] perf clang: Include helpers to BPF scripts |
| Message-ID | <sDDnY-8py-5@gated-at.bofh.it> |
| In reply to | #1522295 |
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 411a38c..db31fb2 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
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:20 +0100 |
| Subject | [PATCH 05/34] tools lib bpf: Add missing bpf map functions |
| Message-ID | <sDDnY-8py-27@gated-at.bofh.it> |
| In reply to | #1522295 |
Add more BPF map operations to libbpf.
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/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..e966248 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_map_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_map_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..5b3e52b 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_map_pin(int fd, const char *pathname);
+int bpf_map_get(const char *pathname);
+
#endif
--
2.10.1
[toc] | [prev] | [next] | [standalone]
| From | "Wangnan (F)" <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-17 04:30 +0100 |
| Subject | Re: [PATCH 05/34] tools lib bpf: Add missing bpf map functions |
| Message-ID | <sElyF-3yp-3@gated-at.bofh.it> |
| In reply to | #1522309 |
On 2016/11/15 12:05, Wang Nan wrote:
> Add more BPF map operations to libbpf.
>
> 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/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..e966248 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_map_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_map_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));
> +}
bpf_map_{pin,get} should be rename to bpf_obj_{pin,get} since they can
be used on BPF program. Thanks to Joe Stringer.
> diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
> index e8ba540..5b3e52b 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_map_pin(int fd, const char *pathname);
> +int bpf_map_get(const char *pathname);
> +
> #endif
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:20 +0100 |
| Subject | [PATCH 31/34] perf clang: Declare BPF functions for BPF scripts automatically |
| Message-ID | <sDDnY-8py-15@gated-at.bofh.it> |
| In reply to | #1522295 |
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 e500525..411a38c 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,
@@ -364,6 +394,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
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:20 +0100 |
| Subject | [PATCH 29/34] perf clang jit: Allow jitted perf hook access BPF maps |
| Message-ID | <sDDnY-8py-17@gated-at.bofh.it> |
| In reply to | #1522295 |
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.
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 jit_helper__map_update_elem(void *ctx, struct bpf_map_def *map,
void *key, void *value, unsigned long flags);
extern int jit_helper__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");
jit_helper__map_update_elem(ctx, &counter, &key, &value, 0);
}
SEC("perfhook:record_end")
void record_end(void *ctx)
{
int key = 0;
int value;
jit_helper__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 | 10 +++++++-
tools/perf/util/jit-helpers.c | 60 +++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/jit-helpers.h | 30 ++++++++++++++++++++++
4 files changed, 100 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..e500525 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,19 @@ 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)),
+ EXPORT(JIT_HELPER_FUNC_NAME(map_get)),
#undef EXPORT
};
diff --git a/tools/perf/util/jit-helpers.c b/tools/perf/util/jit-helpers.c
new file mode 100644
index 0000000..993de14
--- /dev/null
+++ b/tools/perf/util/jit-helpers.c
@@ -0,0 +1,60 @@
+/*
+ * 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_JIT_BPF_MAP_HELPER(pin,
+ PARAMS(const char *pathname),
+ PARAMS(pathname));
+
+JIT_HELPER(int, map_get, const char *pathname)
+{
+ return bpf_map_get(pathname);
+}
diff --git a/tools/perf/util/jit-helpers.h b/tools/perf/util/jit-helpers.h
new file mode 100644
index 0000000..49e0578
--- /dev/null
+++ b/tools/perf/util/jit-helpers.h
@@ -0,0 +1,30 @@
+#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) jit_helper__##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);
+
+extern JIT_HELPER(int, map_get, const char *pathname);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--
2.10.1
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:20 +0100 |
| Subject | [PATCH 34/34] perf clang git: Export getpid() to perf hook |
| Message-ID | <sDDnY-8py-25@gated-at.bofh.it> |
| In reply to | #1522295 |
After this patch perf hooks can retrive pid of perf itself by calling getpid. It is important for excluding event from perf. 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 69aca3c..eedee89 100644 --- a/tools/perf/util/c++/bpf-helper-str.c +++ b/tools/perf/util/c++/bpf-helper-str.c @@ -13,6 +13,7 @@ const char clang_builtin_bpf_helper_str[] = "extern void test__clang_callback(int);\n" "extern int printf(const char *, ...);\n" "extern int puts(const char *);\n" +"extern int getpid(void);\n" "extern int jit_helper__map_update_elem(void *, void *, void *, void *, unsigned long);\n" "extern int jit_helper__map_lookup_elem(void *, void *, void *, void *);\n" "extern int jit_helper__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 db31fb2..d6af336 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
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2016-11-15 05:20 +0100 |
| Subject | [PATCH 09/34] perf tools: Pass context to perf hook functions |
| Message-ID | <sDDnY-8py-33@gated-at.bofh.it> |
| In reply to | #1522295 |
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
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web