@@ -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++/
@@ -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
};
new file mode 100644
@@ -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);
+}
new file mode 100644
@@ -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
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 -- 2.10.1