Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1530618 > unrolled thread

[PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions

Started byWang Nan <wangnan0@huawei.com>
First post2016-11-26 08:20 +0100
Last post2016-11-28 07:50 +0100
Articles 3 — 3 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions Wang Nan <wangnan0@huawei.com> - 2016-11-26 08:20 +0100
    Re: [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT  perfhook functions Alexei Starovoitov <alexei.starovoitov@gmail.com> - 2016-11-26 18:30 +0100
      Re: [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT  perfhook functions "Wangnan (F)" <wangnan0@huawei.com> - 2016-11-28 07:50 +0100

#1530618 — [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions

FromWang Nan <wangnan0@huawei.com>
Date2016-11-26 08:20 +0100
Subject[PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions
Message-ID<sHFrb-3qJ-1@gated-at.bofh.it>
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] | [next] | [standalone]


#1530698 — Re: [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions

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

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

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

[toc] | [prev] | [next] | [standalone]


#1531059 — Re: [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions

From"Wangnan (F)" <wangnan0@huawei.com>
Date2016-11-28 07:50 +0100
SubjectRe: [PATCH v3 20/30] perf clang jit: add PerfModule::doJIT to JIT perfhook functions
Message-ID<sInVg-724-11@gated-at.bofh.it>
In reply to#1530698

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

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

Thank you.

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

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web