Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1215170 > unrolled thread
| Started by | Wang Nan <wangnan0@huawei.com> |
|---|---|
| First post | 2015-08-28 09:10 +0200 |
| Last post | 2015-08-31 16:20 +0200 |
| Articles | 20 on this page of 23 — 4 participants |
Back to article view | Back to linux.kernel
[GIT PULL 00/32] perf tools: filtering events using eBPF programs Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:10 +0200
[PATCH 11/32] perf tools: Add bpf_fd field to evsel and config it Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 03/32] perf tools: Introduce dummy evsel Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 14/32] perf tools: Suppress probing messages when probing by BPF loading Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 07/32] perf probe: Attach trace_probe_event with perf_probe_event Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 08/32] perf record, bpf: Parse and probe eBPF programs probe points Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 02/32] perf tools: Don't set cmdline_group_boundary if no evsel is collected Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 28/32] perf record: Support custom vmlinux path Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 12/32] perf tools: Allow filter option to be applied to bof object Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 27/32] perf tools: Use same BPF program if arguments are identical Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 04/32] perf tools: Make perf depend on libbpf Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 09/32] perf bpf: Collect 'struct perf_probe_event' for bpf_program Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 21/32] perf probe: Reset args and nargs for probe_trace_event when failure Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 16/32] perf tools: Infrastructure for compiling scriptlets when passing '.c' to --event Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 24/32] perf tools: Introduce arch_get_reg_info() for x86 Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 15/32] perf record: Add clang options for compiling BPF scripts Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 18/32] perf test: Add 'perf test BPF' Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 19/32] bpf tools: Load a program with different instances using preprocessor Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 13/32] perf tools: Attach eBPF program to perf event Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
[PATCH 05/32] perf ebpf: Add the libbpf glue Wang Nan <wangnan0@huawei.com> - 2015-08-28 09:20 +0200
Re: [GIT PULL 00/32] perf tools: filtering events using eBPF programs Alexei Starovoitov <ast@plumgrid.com> - 2015-08-29 02:30 +0200
Re: [GIT PULL 00/32] perf tools: filtering events using eBPF programs Arnaldo Carvalho de Melo <acme@redhat.com> - 2015-08-31 16:00 +0200
Re: [GIT PULL 00/32] perf tools: filtering events using eBPF programs "Wangnan (F)" <wangnan0@huawei.com> - 2015-08-31 16:20 +0200
Page 1 of 2 [1] 2 Next page →
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:10 +0200 |
| Subject | [GIT PULL 00/32] perf tools: filtering events using eBPF programs |
| Message-ID | <q2lXr-4sW-3@gated-at.bofh.it> |
Hi Arnaldo,
This time I adjust all Cc and Link field in each patch.
Four new patches (1,2,3,12/32) is newly introduced for fixing a bug
related to '--filter' option. Patch 06/32 is also modified. Please keep
an eye on it.
Since Steven is not very responsive, I still keep patch 31 and 32 in my
tree.
The following changes since commit 327938ee9ea16cc03f02f0e9cc74cdc6ac704cc6:
tools lib traceeveent: Allow for negative numbers in print format (2015-08-27 11:13:53 -0300)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pi3orama/linux tags/perf-ebpf-for-acme-20150828
for you to fetch changes up to 430fc318354a17dddbc66ebb0964a0831f643c77:
bpf: Introduce function for outputing data to perf event (2015-08-28 06:24:43 +0000)
----------------------------------------------------------------
perf BPF related improvements and bugfix:
- Call bpf__clear() in command 'record, top, stat and trace' to ensure
release BPF related resources.
- Correct --filter option when try to apply filter to BPF object.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
----------------------------------------------------------------
He Kuang (5):
perf tools: Move linux/filter.h to tools/include
perf tools: Introduce arch_get_reg_info() for x86
perf record: Support custom vmlinux path
tools lib traceevent: Support function __get_dynamic_array_len
bpf: Introduce function for outputing data to perf event
Wang Nan (27):
bpf tools: New API to get name from a BPF object
perf tools: Don't set cmdline_group_boundary if no evsel is collected
perf tools: Introduce dummy evsel
perf tools: Make perf depend on libbpf
perf ebpf: Add the libbpf glue
perf tools: Enable passing bpf object file to --event
perf probe: Attach trace_probe_event with perf_probe_event
perf record, bpf: Parse and probe eBPF programs probe points
perf bpf: Collect 'struct perf_probe_event' for bpf_program
perf record: Load all eBPF object into kernel
perf tools: Add bpf_fd field to evsel and config it
perf tools: Allow filter option to be applied to bof object
perf tools: Attach eBPF program to perf event
perf tools: Suppress probing messages when probing by BPF loading
perf record: Add clang options for compiling BPF scripts
perf tools: Infrastructure for compiling scriptlets when passing '.c' to --event
perf tests: Enforce LLVM test for BPF test
perf test: Add 'perf test BPF'
bpf tools: Load a program with different instances using preprocessor
perf tools: Fix probe-event.h include
perf probe: Reset args and nargs for probe_trace_event when failure
perf tools: Add BPF_PROLOGUE config options for further patches
perf tools: Add prologue for BPF programs for fetching arguments
perf tools: Generate prologue for BPF programs
perf tools: Use same BPF program if arguments are identical
perf probe: Init symbol as kprobe
perf tools: Support attach BPF program on uprobe events
include/trace/events/bpf.h | 30 +
include/uapi/linux/bpf.h | 7 +
kernel/trace/bpf_trace.c | 23 +
samples/bpf/bpf_helpers.h | 2 +
tools/build/Makefile.feature | 6 +-
tools/include/linux/filter.h | 237 +++++++
tools/lib/bpf/libbpf.c | 168 ++++-
tools/lib/bpf/libbpf.h | 26 +-
tools/lib/traceevent/event-parse.c | 56 +-
tools/lib/traceevent/event-parse.h | 1 +
tools/perf/MANIFEST | 4 +
tools/perf/Makefile.perf | 19 +-
tools/perf/arch/x86/Makefile | 1 +
tools/perf/arch/x86/util/Build | 2 +
tools/perf/arch/x86/util/dwarf-regs.c | 104 ++-
tools/perf/builtin-probe.c | 4 +-
tools/perf/builtin-record.c | 64 +-
tools/perf/builtin-stat.c | 9 +-
tools/perf/builtin-top.c | 11 +-
tools/perf/builtin-trace.c | 6 +-
tools/perf/config/Makefile | 31 +-
tools/perf/tests/Build | 10 +-
tools/perf/tests/bpf-script-example.c | 44 ++
tools/perf/tests/bpf.c | 170 +++++
tools/perf/tests/builtin-test.c | 12 +
tools/perf/tests/llvm.c | 125 +++-
tools/perf/tests/llvm.h | 15 +
tools/perf/tests/make | 4 +-
tools/perf/tests/tests.h | 3 +
tools/perf/util/Build | 2 +
tools/perf/util/bpf-loader.c | 730 +++++++++++++++++++++
tools/perf/util/bpf-loader.h | 95 +++
tools/perf/util/bpf-prologue.c | 442 +++++++++++++
tools/perf/util/bpf-prologue.h | 34 +
tools/perf/util/evlist.c | 107 +++
tools/perf/util/evlist.h | 2 +
tools/perf/util/evsel.c | 49 ++
tools/perf/util/evsel.h | 7 +
tools/perf/util/include/dwarf-regs.h | 7 +
tools/perf/util/parse-events.c | 73 ++-
tools/perf/util/parse-events.h | 4 +
tools/perf/util/parse-events.l | 6 +
tools/perf/util/parse-events.y | 29 +-
tools/perf/util/probe-event.c | 79 ++-
tools/perf/util/probe-event.h | 8 +-
tools/perf/util/probe-file.c | 5 +-
tools/perf/util/probe-finder.c | 4 +
.../perf/util/scripting-engines/trace-event-perl.c | 1 +
.../util/scripting-engines/trace-event-python.c | 1 +
49 files changed, 2759 insertions(+), 120 deletions(-)
create mode 100644 include/trace/events/bpf.h
create mode 100644 tools/include/linux/filter.h
create mode 100644 tools/perf/tests/bpf-script-example.c
create mode 100644 tools/perf/tests/bpf.c
create mode 100644 tools/perf/tests/llvm.h
create mode 100644 tools/perf/util/bpf-loader.c
create mode 100644 tools/perf/util/bpf-loader.h
create mode 100644 tools/perf/util/bpf-prologue.c
create mode 100644 tools/perf/util/bpf-prologue.h
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 11/32] perf tools: Add bpf_fd field to evsel and config it |
| Message-ID | <q2m78-4Ey-7@gated-at.bofh.it> |
| In reply to | #1215170 |
This patch adds a bpf_fd field to 'struct evsel' then introduces method
to config it. In bpf-loader, a bpf__foreach_tev() function is added,
which calls the callback function for each 'struct probe_trace_event'
events for each bpf program with their file descriptors. In evlist.c,
perf_evlist__add_bpf() is introduced to add all bpf events into evlist.
The event names are found from probe_trace_event structure.
'perf record' calls perf_evlist__add_bpf().
Since bpf-loader.c will not be built if libbpf is turned off, an empty
bpf__foreach_tev() is defined in bpf-loader.h to avoid compiling
error.
This patch iterates over 'struct probe_trace_event' instead of
'struct probe_trace_event' during the loop for further patches, which
will generate multiple instances form one BPF program and install then
onto different 'struct probe_trace_event'.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/n/1436445342-1402-25-git-send-email-wangnan0@huawei.com
---
tools/perf/builtin-record.c | 6 ++++++
tools/perf/util/bpf-loader.c | 41 +++++++++++++++++++++++++++++++++++++++++
tools/perf/util/bpf-loader.h | 13 +++++++++++++
tools/perf/util/evlist.c | 41 +++++++++++++++++++++++++++++++++++++++++
tools/perf/util/evlist.h | 1 +
tools/perf/util/evsel.c | 1 +
tools/perf/util/evsel.h | 1 +
7 files changed, 104 insertions(+)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index c335ac5..5051d3b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1173,6 +1173,12 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
goto out_symbol_exit;
}
+ err = perf_evlist__add_bpf(rec->evlist);
+ if (err < 0) {
+ pr_err("Failed to add events from BPF object(s)\n");
+ goto out_symbol_exit;
+ }
+
symbol__init(NULL);
if (symbol_conf.kptr_restrict)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index d63a594..126aa71 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -286,6 +286,47 @@ errout:
return err;
}
+int bpf__foreach_tev(bpf_prog_iter_callback_t func, void *arg)
+{
+ struct bpf_object *obj, *tmp;
+ struct bpf_program *prog;
+ int err;
+
+ bpf_object__for_each_safe(obj, tmp) {
+ bpf_object__for_each_program(prog, obj) {
+ struct probe_trace_event *tev;
+ struct perf_probe_event *pev;
+ struct bpf_prog_priv *priv;
+ int i, fd;
+
+ err = bpf_program__get_private(prog,
+ (void **)&priv);
+ if (err || !priv) {
+ pr_debug("bpf: failed to get private field\n");
+ return -EINVAL;
+ }
+
+ pev = &priv->pev;
+ for (i = 0; i < pev->ntevs; i++) {
+ tev = &pev->tevs[i];
+
+ fd = bpf_program__fd(prog);
+ if (fd < 0) {
+ pr_debug("bpf: failed to get file descriptor\n");
+ return fd;
+ }
+
+ err = func(tev, fd, arg);
+ if (err) {
+ pr_debug("bpf: call back failed, stop iterate\n");
+ return err;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
#define bpf__strerror_head(err, buf, size) \
char sbuf[STRERR_BUFSIZE], *emsg;\
if (!size)\
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 4d7552e..34656f8 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -7,10 +7,14 @@
#include <linux/compiler.h>
#include <string.h>
+#include "probe-event.h"
#include "debug.h"
#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
+typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
+ int fd, void *arg);
+
#ifdef HAVE_LIBBPF_SUPPORT
int bpf__prepare_load(const char *filename);
int bpf__strerror_prepare_load(const char *filename, int err,
@@ -23,6 +27,8 @@ int bpf__load(void);
int bpf__strerror_load(int err, char *buf, size_t size);
void bpf__clear(void);
+
+int bpf__foreach_tev(bpf_prog_iter_callback_t func, void *arg);
#else
static inline int bpf__prepare_load(const char *filename __maybe_unused)
{
@@ -36,6 +42,13 @@ static inline int bpf__load(void) { return 0; }
static inline void bpf__clear(void) { }
static inline int
+bpf__foreach_tev(bpf_prog_iter_callback_t func __maybe_unused,
+ void *arg __maybe_unused)
+{
+ return 0;
+}
+
+static inline int
__bpf_strerror(char *buf, size_t size)
{
if (!size)
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 30fc327..3bedf64 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -14,6 +14,7 @@
#include "target.h"
#include "evlist.h"
#include "evsel.h"
+#include "bpf-loader.h"
#include "debug.h"
#include <unistd.h>
@@ -194,6 +195,46 @@ error:
return -ENOMEM;
}
+static int add_bpf_event(struct probe_trace_event *tev, int fd,
+ void *arg)
+{
+ struct perf_evlist *evlist = arg;
+ struct perf_evsel *pos;
+ struct list_head list;
+ int err, idx, entries;
+
+ pr_debug("add bpf event %s:%s and attach bpf program %d\n",
+ tev->group, tev->event, fd);
+ INIT_LIST_HEAD(&list);
+ idx = evlist->nr_entries;
+
+ pr_debug("adding %s:%s\n", tev->group, tev->event);
+ err = parse_events_add_tracepoint(&list, &idx, tev->group,
+ tev->event);
+ if (err) {
+ struct perf_evsel *evsel, *tmp;
+
+ pr_err("Failed to add BPF event %s:%s\n",
+ tev->group, tev->event);
+ list_for_each_entry_safe(evsel, tmp, &list, node) {
+ list_del(&evsel->node);
+ perf_evsel__delete(evsel);
+ }
+ return -EINVAL;
+ }
+
+ list_for_each_entry(pos, &list, node)
+ pos->bpf_fd = fd;
+ entries = idx - evlist->nr_entries;
+ perf_evlist__splice_list_tail(evlist, &list, entries);
+ return 0;
+}
+
+int perf_evlist__add_bpf(struct perf_evlist *evlist)
+{
+ return bpf__foreach_tev(add_bpf_event, evlist);
+}
+
static int perf_evlist__add_attrs(struct perf_evlist *evlist,
struct perf_event_attr *attrs, size_t nr_attrs)
{
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index df4820e..779aa27 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -72,6 +72,7 @@ void perf_evlist__delete(struct perf_evlist *evlist);
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
int perf_evlist__add_default(struct perf_evlist *evlist);
+int perf_evlist__add_bpf(struct perf_evlist *evlist);
int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
struct perf_event_attr *attrs, size_t nr_attrs);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 35947f5..77a425f 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -206,6 +206,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
evsel->leader = evsel;
evsel->unit = "";
evsel->scale = 1.0;
+ evsel->bpf_fd = -1;
INIT_LIST_HEAD(&evsel->node);
INIT_LIST_HEAD(&evsel->config_terms);
perf_evsel__object.init(evsel);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 443995b..9618099 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -116,6 +116,7 @@ struct perf_evsel {
bool cmdline_group_boundary;
bool is_dummy;
struct list_head config_terms;
+ int bpf_fd;
};
union u64_swap {
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 03/32] perf tools: Introduce dummy evsel |
| Message-ID | <q2m78-4Ey-11@gated-at.bofh.it> |
| In reply to | #1215170 |
This patch allows linking dummy evsel onto evlist as a placeholder. It
is for following patch which allows passing BPF object using '--event
object.o'.
Doesn't link other event selectors, if passing a BPF object file to
'--event', nothing is linked onto evlist. Instead, events described in
BPF object file are probed and linked in a delayed manner because we
want do all probing work together. Therefore, evsel for events in BPF
object would be linked at the end of evlist. Which causes a small
problem that, if passing '--filter' setting after object file, the
filter option won't be correctly applied to those events.
This patch links dummy onto evlist, so following --filter can be
collected by the dummy evsel. For this reason dummy evsels are set to
PERF_TYPE_TRACEPOINT.
Due to the possibility of existance of dummy evsel,
perf_evlist__purge_dummy() must be called right after parse_options().
This patch adds it to record, top, trace and stat builtin commands.
Further patch moves it down after real BPF events are processed with.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1440742821-44548-4-git-send-email-wangnan0@huawei.com
---
tools/perf/builtin-record.c | 2 ++
tools/perf/builtin-stat.c | 1 +
tools/perf/builtin-top.c | 1 +
tools/perf/builtin-trace.c | 1 +
tools/perf/util/evlist.c | 19 +++++++++++++++++++
tools/perf/util/evlist.h | 1 +
tools/perf/util/evsel.c | 32 ++++++++++++++++++++++++++++++++
tools/perf/util/evsel.h | 6 ++++++
tools/perf/util/parse-events.c | 25 +++++++++++++++++++++----
9 files changed, 84 insertions(+), 4 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a660022..81829de 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1112,6 +1112,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
argc = parse_options(argc, argv, record_options, record_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
+ perf_evlist__purge_dummy(rec->evlist);
+
if (!argc && target__none(&rec->opts.target))
usage_with_options(record_usage, record_options);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 7aa039b..99b62f1 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1208,6 +1208,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
argc = parse_options(argc, argv, options, stat_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
+ perf_evlist__purge_dummy(evsel_list);
interval = stat_config.interval;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 8c465c8..246203b 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1198,6 +1198,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
perf_config(perf_top_config, &top);
argc = parse_options(argc, argv, options, top_usage, 0);
+ perf_evlist__purge_dummy(top.evlist);
if (argc)
usage_with_options(top_usage, options);
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 2f1162d..ef5fde6 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -3080,6 +3080,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
+ perf_evlist__purge_dummy(trace.evlist);
if (trace.trace_pgfaults) {
trace.opts.sample_address = true;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index e9a5d43..30fc327 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1694,3 +1694,22 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
tracking_evsel->tracking = true;
}
+
+void perf_evlist__purge_dummy(struct perf_evlist *evlist)
+{
+ struct perf_evsel *pos, *n;
+
+ /*
+ * Remove all dummy events.
+ * During linking, we don't touch anything except link
+ * it into evlist. As a result, we don't
+ * need to adjust evlist->nr_entries during removal.
+ */
+
+ evlist__for_each_safe(evlist, n, pos) {
+ if (perf_evsel__is_dummy(pos)) {
+ list_del_init(&pos->node);
+ perf_evsel__delete(pos);
+ }
+ }
+}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 436e358..df4820e 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -180,6 +180,7 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist);
void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
struct list_head *list,
int nr_entries);
+void perf_evlist__purge_dummy(struct perf_evlist *evlist);
static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist)
{
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index b096ef7..35947f5 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -212,6 +212,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
perf_evsel__calc_id_pos(evsel);
evsel->cmdline_group_boundary = false;
+ evsel->is_dummy = false;
}
struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
@@ -224,6 +225,37 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
return evsel;
}
+struct perf_evsel *perf_evsel__new_dummy(const char *name)
+{
+ struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
+
+ if (!evsel)
+ return NULL;
+
+ /*
+ * Don't need call perf_evsel__init() for dummy evsel.
+ * Keep it simple.
+ */
+ evsel->name = strdup(name);
+ if (!evsel->name)
+ goto out_free;
+
+ INIT_LIST_HEAD(&evsel->node);
+ INIT_LIST_HEAD(&evsel->config_terms);
+
+ evsel->cmdline_group_boundary = false;
+ /*
+ * Set dummy evsel as TRACEPOINT event so it can collect filter
+ * options.
+ */
+ evsel->attr.type = PERF_TYPE_TRACEPOINT;
+ evsel->is_dummy = true;
+ return evsel;
+out_free:
+ free(evsel);
+ return NULL;
+}
+
struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
{
struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 93ac6b1..443995b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -114,6 +114,7 @@ struct perf_evsel {
struct perf_evsel *leader;
char *group_name;
bool cmdline_group_boundary;
+ bool is_dummy;
struct list_head config_terms;
};
@@ -149,6 +150,11 @@ int perf_evsel__object_config(size_t object_size,
void (*fini)(struct perf_evsel *evsel));
struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx);
+struct perf_evsel *perf_evsel__new_dummy(const char *name);
+static inline bool perf_evsel__is_dummy(struct perf_evsel *evsel)
+{
+ return evsel->is_dummy;
+}
static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)
{
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 14cd7e3..71d91fb 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1141,7 +1141,7 @@ int parse_events(struct perf_evlist *evlist, const char *str,
perf_pmu__parse_cleanup();
if (!ret) {
int entries = data.idx - evlist->nr_entries;
- struct perf_evsel *last;
+ struct perf_evsel *last = NULL;
if (!list_empty(&data.list)) {
last = list_entry(data.list.prev,
@@ -1149,8 +1149,25 @@ int parse_events(struct perf_evlist *evlist, const char *str,
last->cmdline_group_boundary = true;
}
- perf_evlist__splice_list_tail(evlist, &data.list, entries);
- evlist->nr_groups += data.nr_groups;
+ if (last && perf_evsel__is_dummy(last)) {
+ if (!list_is_singular(&data.list)) {
+ parse_events_evlist_error(&data, 0,
+ "Dummy evsel error: not on a singular list");
+ return -1;
+ }
+ /*
+ * We are introducing a dummy event. Don't touch
+ * anything, just link it.
+ *
+ * Don't use perf_evlist__splice_list_tail() since
+ * it alerts evlist->nr_entries, which affect header
+ * of resulting perf.data.
+ */
+ list_splice_tail(&data.list, &evlist->entries);
+ } else {
+ perf_evlist__splice_list_tail(evlist, &data.list, entries);
+ evlist->nr_groups += data.nr_groups;
+ }
return 0;
}
@@ -1256,7 +1273,7 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist,
struct perf_evsel *last = NULL;
int err;
- if (evlist->nr_entries > 0)
+ if (!list_empty(&evlist->entries))
last = perf_evlist__last(evlist);
do {
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 14/32] perf tools: Suppress probing messages when probing by BPF loading |
| Message-ID | <q2m78-4Ey-13@gated-at.bofh.it> |
| In reply to | #1215170 |
This patch suppresses message output by add_perf_probe_events() and
del_perf_probe_events() if they are triggered by BPF loading. Before
this patch, when using 'perf record' with BPF object/source as event
selector, following message will be output:
Added new event:
perf_bpf_probe:lock_page_ret (on __lock_page%return)
You can now use it in all perf tools, such as:
perf record -e perf_bpf_probe:lock_page_ret -aR sleep 1
...
Removed event: perf_bpf_probe:lock_page_ret
Which is misleading, especially 'use it in all perf tools' because they
will be removed after 'pref record' exit.
In this patch, a 'silent' field is appended into probe_conf to control
output. bpf__{,un}probe() set it to true when calling
{add,del}_perf_probe_events().
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/n/1440151770-129878-12-git-send-email-wangnan0@huawei.com
---
tools/perf/util/bpf-loader.c | 6 ++++++
tools/perf/util/probe-event.c | 17 ++++++++++++-----
tools/perf/util/probe-event.h | 1 +
tools/perf/util/probe-file.c | 5 ++++-
4 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index c3bc0a8..77eeb99 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -188,6 +188,7 @@ static bool is_probed;
int bpf__unprobe(void)
{
struct strfilter *delfilter;
+ bool old_silent = probe_conf.silent;
int ret;
if (!is_probed)
@@ -199,7 +200,9 @@ int bpf__unprobe(void)
return -ENOMEM;
}
+ probe_conf.silent = true;
ret = del_perf_probe_events(delfilter);
+ probe_conf.silent = old_silent;
strfilter__delete(delfilter);
if (ret < 0 && is_probed)
pr_debug("Error: failed to delete events: %s\n",
@@ -215,6 +218,7 @@ int bpf__probe(void)
struct bpf_object *obj, *tmp;
struct bpf_program *prog;
struct perf_probe_event *pevs;
+ bool old_silent = probe_conf.silent;
pevs = calloc(MAX_PROBES, sizeof(pevs[0]));
if (!pevs)
@@ -235,9 +239,11 @@ int bpf__probe(void)
}
}
+ probe_conf.silent = true;
probe_conf.max_probes = MAX_PROBES;
/* Let add_perf_probe_events generates probe_trace_event (tevs) */
err = add_perf_probe_events(pevs, nr_events, false);
+ probe_conf.silent = old_silent;
/* add_perf_probe_events return negative when fail */
if (err < 0) {
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 57a7bae..e720913 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -52,7 +52,9 @@
#define PERFPROBE_GROUP "probe"
bool probe_event_dry_run; /* Dry run flag */
-struct probe_conf probe_conf;
+struct probe_conf probe_conf = {
+ .silent = false,
+};
#define semantic_error(msg ...) pr_err("Semantic error :" msg)
@@ -2192,10 +2194,12 @@ static int show_perf_probe_event(const char *group, const char *event,
ret = perf_probe_event__sprintf(group, event, pev, module, &buf);
if (ret >= 0) {
- if (use_stdout)
+ if (use_stdout && !probe_conf.silent)
printf("%s\n", buf.buf);
- else
+ else if (!probe_conf.silent)
pr_info("%s\n", buf.buf);
+ else
+ pr_debug("%s\n", buf.buf);
}
strbuf_release(&buf);
@@ -2418,7 +2422,10 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
}
ret = 0;
- pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
+ if (!probe_conf.silent)
+ pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
+ else
+ pr_debug("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
for (i = 0; i < ntevs; i++) {
tev = &tevs[i];
/* Skip if the symbol is out of .text or blacklisted */
@@ -2454,7 +2461,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
warn_uprobe_event_compat(tev);
/* Note that it is possible to skip all events because of blacklist */
- if (ret >= 0 && event) {
+ if (ret >= 0 && event && !probe_conf.silent) {
/* Show how to use the event. */
pr_info("\nYou can now use it in all perf tools, such as:\n\n");
pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", group, event);
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 915f0d8..3ab9c3e 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -13,6 +13,7 @@ struct probe_conf {
bool force_add;
bool no_inlines;
int max_probes;
+ bool silent;
};
extern struct probe_conf probe_conf;
extern bool probe_event_dry_run;
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index bbb2437..db7bd4c 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -267,7 +267,10 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
goto error;
}
- pr_info("Removed event: %s\n", ent->s);
+ if (!probe_conf.silent)
+ pr_info("Removed event: %s\n", ent->s);
+ else
+ pr_debug("Removed event: %s\n", ent->s);
return 0;
error:
pr_warning("Failed to delete event: %s\n",
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 07/32] perf probe: Attach trace_probe_event with perf_probe_event |
| Message-ID | <q2m78-4Ey-17@gated-at.bofh.it> |
| In reply to | #1215170 |
This patch drops struct __event_package structure. Instead, it adds
trace_probe_event into 'struct perf_probe_event'.
trace_probe_event information gives further patches a chance to access
actual probe points and actual arguments. Using them, bpf_loader will
be able to attach one bpf program to different probing points of a
inline functions (which has multiple probing points) and glob
functions. Moreover, by reading arguments information, bpf code for
reading those arguments can be generated.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/n/1436445342-1402-22-git-send-email-wangnan0@huawei.com
---
tools/perf/builtin-probe.c | 4 ++-
tools/perf/util/probe-event.c | 60 +++++++++++++++++++++----------------------
tools/perf/util/probe-event.h | 6 ++++-
3 files changed, 38 insertions(+), 32 deletions(-)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index b81cec3..826d452 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -496,7 +496,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
usage_with_options(probe_usage, options);
}
- ret = add_perf_probe_events(params.events, params.nevents);
+ ret = add_perf_probe_events(params.events,
+ params.nevents,
+ true);
if (ret < 0) {
pr_err_with_code(" Error: Failed to add events.", ret);
return ret;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index eb5f18b..57a7bae 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1985,6 +1985,9 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
struct perf_probe_arg_field *field, *next;
int i;
+ if (pev->ntevs)
+ cleanup_perf_probe_event(pev);
+
free(pev->event);
free(pev->group);
free(pev->target);
@@ -2759,61 +2762,58 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
return find_probe_trace_events_from_map(pev, tevs);
}
-struct __event_package {
- struct perf_probe_event *pev;
- struct probe_trace_event *tevs;
- int ntevs;
-};
-
-int add_perf_probe_events(struct perf_probe_event *pevs, int npevs)
+int cleanup_perf_probe_event(struct perf_probe_event *pev)
{
- int i, j, ret;
- struct __event_package *pkgs;
+ int i;
- ret = 0;
- pkgs = zalloc(sizeof(struct __event_package) * npevs);
+ if (!pev || !pev->ntevs)
+ return 0;
- if (pkgs == NULL)
- return -ENOMEM;
+ for (i = 0; i < pev->ntevs; i++)
+ clear_probe_trace_event(&pev->tevs[i]);
+
+ zfree(&pev->tevs);
+ pev->ntevs = 0;
+ return 0;
+}
+
+int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
+ bool cleanup)
+{
+ int i, ret;
ret = init_symbol_maps(pevs->uprobes);
- if (ret < 0) {
- free(pkgs);
+ if (ret < 0)
return ret;
- }
/* Loop 1: convert all events */
for (i = 0; i < npevs; i++) {
- pkgs[i].pev = &pevs[i];
/* Init kprobe blacklist if needed */
- if (!pkgs[i].pev->uprobes)
+ if (pevs[i].uprobes)
kprobe_blacklist__init();
/* Convert with or without debuginfo */
- ret = convert_to_probe_trace_events(pkgs[i].pev,
- &pkgs[i].tevs);
- if (ret < 0)
+ ret = convert_to_probe_trace_events(&pevs[i], &pevs[i].tevs);
+ if (ret < 0) {
+ cleanup = true;
goto end;
- pkgs[i].ntevs = ret;
+ }
+ pevs[i].ntevs = ret;
}
/* This just release blacklist only if allocated */
kprobe_blacklist__release();
/* Loop 2: add all events */
for (i = 0; i < npevs; i++) {
- ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
- pkgs[i].ntevs,
+ ret = __add_probe_trace_events(&pevs[i], pevs[i].tevs,
+ pevs[i].ntevs,
probe_conf.force_add);
if (ret < 0)
break;
}
end:
/* Loop 3: cleanup and free trace events */
- for (i = 0; i < npevs; i++) {
- for (j = 0; j < pkgs[i].ntevs; j++)
- clear_probe_trace_event(&pkgs[i].tevs[j]);
- zfree(&pkgs[i].tevs);
- }
- free(pkgs);
+ for (i = 0; cleanup && (i < npevs); i++)
+ cleanup_perf_probe_event(&pevs[i]);
exit_symbol_maps();
return ret;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 6e7ec68..915f0d8 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -87,6 +87,8 @@ struct perf_probe_event {
bool uprobes; /* Uprobe event flag */
char *target; /* Target binary */
struct perf_probe_arg *args; /* Arguments */
+ struct probe_trace_event *tevs;
+ int ntevs;
};
/* Line range */
@@ -137,8 +139,10 @@ extern void line_range__clear(struct line_range *lr);
/* Initialize line range */
extern int line_range__init(struct line_range *lr);
-extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
+extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
+ bool cleanup);
extern int del_perf_probe_events(struct strfilter *filter);
+extern int cleanup_perf_probe_event(struct perf_probe_event *pev);
extern int show_perf_probe_events(struct strfilter *filter);
extern int show_line_range(struct line_range *lr, const char *module,
bool user);
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 08/32] perf record, bpf: Parse and probe eBPF programs probe points |
| Message-ID | <q2m78-4Ey-21@gated-at.bofh.it> |
| In reply to | #1215170 |
This patch introduces bpf__{un,}probe() functions to enable callers to
create kprobe points based on section names of BPF programs. It parses
the section names of each eBPF program and creates corresponding 'struct
perf_probe_event' structures. The parse_perf_probe_command() function is
used to do the main parsing work.
Parsing result is stored into an array to satisify
add_perf_probe_events(). It accepts an array of 'struct perf_probe_event'
and do all the work in one call.
Define PERF_BPF_PROBE_GROUP as "perf_bpf_probe", which will be used as
the group name of all eBPF probing points.
probe_conf.max_probes is set to MAX_PROBES to support glob matching.
Before ending of bpf__probe(), data in each 'struct perf_probe_event' is
cleaned. Things will be changed by following patches because they need
'struct probe_trace_event' in them,
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/n/1436445342-1402-21-git-send-email-wangnan0@huawei.com
Link: http://lkml.kernel.org/n/1436445342-1402-23-git-send-email-wangnan0@huawei.com
[Merged by two patches]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-record.c | 19 ++++++-
tools/perf/util/bpf-loader.c | 133 +++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/bpf-loader.h | 13 +++++
3 files changed, 164 insertions(+), 1 deletion(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 31934b1..8833186 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1140,7 +1140,23 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
if (err)
goto out_bpf_clear;
- err = -ENOMEM;
+ /*
+ * bpf__probe must be called before symbol__init() because we
+ * need init_symbol_maps. If called after symbol__init,
+ * symbol_conf.sort_by_name won't take effect.
+ *
+ * bpf__unprobe() is safe even if bpf__probe() failed, and it
+ * also calls symbol__init. Therefore, goto out_symbol_exit
+ * is safe when probe failed.
+ */
+ err = bpf__probe();
+ if (err) {
+ bpf__strerror_probe(err, errbuf, sizeof(errbuf));
+
+ pr_err("Probing at events in BPF object failed.\n");
+ pr_err("\t%s\n", errbuf);
+ goto out_symbol_exit;
+ }
symbol__init(NULL);
@@ -1201,6 +1217,7 @@ out_symbol_exit:
perf_evlist__delete(rec->evlist);
symbol__exit();
auxtrace_record__free(rec->itr);
+ bpf__unprobe();
out_bpf_clear:
bpf__clear();
return err;
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 88531ea..435f52e 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -9,6 +9,8 @@
#include "perf.h"
#include "debug.h"
#include "bpf-loader.h"
+#include "probe-event.h"
+#include "probe-finder.h"
#define DEFINE_PRINT_FN(name, level) \
static int libbpf_##name(const char *fmt, ...) \
@@ -28,6 +30,58 @@ DEFINE_PRINT_FN(debug, 1)
static bool libbpf_initialized;
+static int
+config_bpf_program(struct bpf_program *prog, struct perf_probe_event *pev)
+{
+ const char *config_str;
+ int err;
+
+ config_str = bpf_program__title(prog, false);
+ if (!config_str) {
+ pr_debug("bpf: unable to get title for program\n");
+ return -EINVAL;
+ }
+
+ pr_debug("bpf: config program '%s'\n", config_str);
+ err = parse_perf_probe_command(config_str, pev);
+ if (err < 0) {
+ pr_debug("bpf: '%s' is not a valid config string\n",
+ config_str);
+ /* parse failed, don't need clear pev. */
+ return -EINVAL;
+ }
+
+ if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
+ pr_debug("bpf: '%s': group for event is set and not '%s'.\n",
+ config_str, PERF_BPF_PROBE_GROUP);
+ err = -EINVAL;
+ goto errout;
+ } else if (!pev->group)
+ pev->group = strdup(PERF_BPF_PROBE_GROUP);
+
+ if (!pev->group) {
+ pr_debug("bpf: strdup failed\n");
+ err = -ENOMEM;
+ goto errout;
+ }
+
+ if (!pev->event) {
+ pr_debug("bpf: '%s': event name is missing\n",
+ config_str);
+ err = -EINVAL;
+ goto errout;
+ }
+
+ pr_debug("bpf: config '%s' is ok\n", config_str);
+
+ return 0;
+
+errout:
+ if (pev)
+ clear_perf_probe_event(pev);
+ return err;
+}
+
int bpf__prepare_load(const char *filename)
{
struct bpf_object *obj;
@@ -59,6 +113,74 @@ void bpf__clear(void)
bpf_object__close(obj);
}
+static bool is_probed;
+
+int bpf__unprobe(void)
+{
+ struct strfilter *delfilter;
+ int ret;
+
+ if (!is_probed)
+ return 0;
+
+ delfilter = strfilter__new(PERF_BPF_PROBE_GROUP ":*", NULL);
+ if (!delfilter) {
+ pr_debug("Failed to create delfilter when unprobing\n");
+ return -ENOMEM;
+ }
+
+ ret = del_perf_probe_events(delfilter);
+ strfilter__delete(delfilter);
+ if (ret < 0 && is_probed)
+ pr_debug("Error: failed to delete events: %s\n",
+ strerror(-ret));
+ else
+ is_probed = false;
+ return ret < 0 ? ret : 0;
+}
+
+int bpf__probe(void)
+{
+ int err, nr_events = 0;
+ struct bpf_object *obj, *tmp;
+ struct bpf_program *prog;
+ struct perf_probe_event *pevs;
+
+ pevs = calloc(MAX_PROBES, sizeof(pevs[0]));
+ if (!pevs)
+ return -ENOMEM;
+
+ bpf_object__for_each_safe(obj, tmp) {
+ bpf_object__for_each_program(prog, obj) {
+ err = config_bpf_program(prog, &pevs[nr_events++]);
+ if (err < 0)
+ goto out;
+
+ if (nr_events >= MAX_PROBES) {
+ pr_debug("Too many (more than %d) events\n",
+ MAX_PROBES);
+ err = -ERANGE;
+ goto out;
+ };
+ }
+ }
+
+ probe_conf.max_probes = MAX_PROBES;
+ /* Let add_perf_probe_events generates probe_trace_event (tevs) */
+ err = add_perf_probe_events(pevs, nr_events, false);
+
+ /* add_perf_probe_events return negative when fail */
+ if (err < 0) {
+ pr_debug("bpf probe: failed to probe events\n");
+ } else
+ is_probed = true;
+out:
+ while (nr_events > 0)
+ clear_perf_probe_event(&pevs[--nr_events]);
+ free(pevs);
+ return err < 0 ? err : 0;
+}
+
#define bpf__strerror_head(err, buf, size) \
char sbuf[STRERR_BUFSIZE], *emsg;\
if (!size)\
@@ -90,3 +212,14 @@ int bpf__strerror_prepare_load(const char *filename, int err,
bpf__strerror_end(buf, size);
return 0;
}
+
+int bpf__strerror_probe(int err, char *buf, size_t size)
+{
+ bpf__strerror_head(err, buf, size);
+ bpf__strerror_entry(ERANGE, "Too many (more than %d) events",
+ MAX_PROBES);
+ bpf__strerror_entry(ENOENT, "Selected kprobe point doesn't exist.");
+ bpf__strerror_entry(EEXIST, "Selected kprobe point already exist, try perf probe -d '*'.");
+ bpf__strerror_end(buf, size);
+ return 0;
+}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 12be630..6b09a85 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -9,10 +9,15 @@
#include <string.h>
#include "debug.h"
+#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
+
#ifdef HAVE_LIBBPF_SUPPORT
int bpf__prepare_load(const char *filename);
int bpf__strerror_prepare_load(const char *filename, int err,
char *buf, size_t size);
+int bpf__probe(void);
+int bpf__unprobe(void);
+int bpf__strerror_probe(int err, char *buf, size_t size);
void bpf__clear(void);
#else
@@ -22,6 +27,8 @@ static inline int bpf__prepare_load(const char *filename __maybe_unused)
return -1;
}
+static inline int bpf__probe(void) { return 0; }
+static inline int bpf__unprobe(void) { return 0; }
static inline void bpf__clear(void) { }
static inline int
@@ -43,5 +50,11 @@ bpf__strerror_prepare_load(const char *filename __maybe_unused,
{
return __bpf_strerror(buf, size);
}
+
+static inline int bpf__strerror_probe(int err __maybe_unused,
+ char *buf, size_t size)
+{
+ return __bpf_strerror(buf, size);
+}
#endif
#endif
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 02/32] perf tools: Don't set cmdline_group_boundary if no evsel is collected |
| Message-ID | <q2m78-4Ey-25@gated-at.bofh.it> |
| In reply to | #1215170 |
If parse_events__scanner() collects no entry, perf_evlist__last(evlist)
is invalid. Then setting of cmdline_group_boundary touches invalid.
It could happend in currect BPF implementation. See [1]. Although it
can be fixed, for safety reason it whould be better to introduce this
check.
Instead of checking number of entries, check data.list instead, so we
can add dummy evsel here.
[1]: http://lkml.kernel.org/n/1436445342-1402-19-git-send-email-wangnan0@huawei.com
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/r/1440742821-44548-3-git-send-email-wangnan0@huawei.com
---
tools/perf/util/parse-events.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index d826e6f..14cd7e3 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1143,10 +1143,14 @@ int parse_events(struct perf_evlist *evlist, const char *str,
int entries = data.idx - evlist->nr_entries;
struct perf_evsel *last;
+ if (!list_empty(&data.list)) {
+ last = list_entry(data.list.prev,
+ struct perf_evsel, node);
+ last->cmdline_group_boundary = true;
+ }
+
perf_evlist__splice_list_tail(evlist, &data.list, entries);
evlist->nr_groups += data.nr_groups;
- last = perf_evlist__last(evlist);
- last->cmdline_group_boundary = true;
return 0;
}
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 28/32] perf record: Support custom vmlinux path |
| Message-ID | <q2m78-4Ey-27@gated-at.bofh.it> |
| In reply to | #1215170 |
From: He Kuang <hekuang@huawei.com>
Make perf-record command support --vmlinux option if BPF_PROLOGUE is on.
'perf record' needs vmlinux as the source of DWARF info to generate
prologue for BPF programs, so path of vmlinux should be specified.
Short name 'k' has been taken by 'clockid'. This patch skips the short
option name and use '--vmlinux' for vmlinux path.
Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/n/1436445342-1402-38-git-send-email-wangnan0@huawei.com
---
tools/perf/builtin-record.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 212718c..8eb39d5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1100,6 +1100,10 @@ struct option __record_options[] = {
"clang binary to use for compiling BPF scriptlets"),
OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
"options passed to clang when compiling BPF scriptlets"),
+#ifdef HAVE_BPF_PROLOGUE
+ OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
+ "file", "vmlinux pathname"),
+#endif
#endif
OPT_END()
};
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 12/32] perf tools: Allow filter option to be applied to bof object |
| Message-ID | <q2m78-4Ey-29@gated-at.bofh.it> |
| In reply to | #1215170 |
Before this patch, --filter options can't be applied to BPF object
'events'. For example, the following command:
# perf record -e cycles -e test_bpf.o --exclude-perf -a sleep 1
doesn't apply '--exclude-perf' to events in test_bpf.o. Instead, the
filter will be applied to 'cycles' event. This is caused by the delay
manner of adding real BPF events. Because all BPF probing points are
probed by one call, we can't add real events until all BPF objects
are collected. In previous patch (perf tools: Enable passing bpf object
file to --event), nothing is appended to evlist.
This patch fixes this by utilizing the dummy event linked during
parse_events(). Filter settings goes to dummy event, and be synced with
real events in add_bpf_event().
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/r/1440742821-44548-5-git-send-email-wangnan0@huawei.com
---
tools/perf/builtin-record.c | 6 ++++-
tools/perf/util/bpf-loader.c | 8 ++++++-
tools/perf/util/bpf-loader.h | 2 ++
tools/perf/util/evlist.c | 53 +++++++++++++++++++++++++++++++++++++++++---
4 files changed, 64 insertions(+), 5 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 5051d3b..fd56a5b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1113,7 +1113,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
argc = parse_options(argc, argv, record_options, record_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
- perf_evlist__purge_dummy(rec->evlist);
if (!argc && target__none(&rec->opts.target))
usage_with_options(record_usage, record_options);
@@ -1178,6 +1177,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
pr_err("Failed to add events from BPF object(s)\n");
goto out_symbol_exit;
}
+ /*
+ * Until now let's purge dummy event. Filter options should
+ * have been attached to real events by perf_evlist__add_bpf().
+ */
+ perf_evlist__purge_dummy(rec->evlist);
symbol__init(NULL);
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 126aa71..c3bc0a8 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -293,6 +293,12 @@ int bpf__foreach_tev(bpf_prog_iter_callback_t func, void *arg)
int err;
bpf_object__for_each_safe(obj, tmp) {
+ const char *obj_name;
+
+ obj_name = bpf_object__get_name(obj);
+ if (!obj_name)
+ obj_name = "[unknown]";
+
bpf_object__for_each_program(prog, obj) {
struct probe_trace_event *tev;
struct perf_probe_event *pev;
@@ -316,7 +322,7 @@ int bpf__foreach_tev(bpf_prog_iter_callback_t func, void *arg)
return fd;
}
- err = func(tev, fd, arg);
+ err = func(tev, obj_name, fd, arg);
if (err) {
pr_debug("bpf: call back failed, stop iterate\n");
return err;
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 34656f8..323e664 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -6,6 +6,7 @@
#define __BPF_LOADER_H
#include <linux/compiler.h>
+#include <linux/perf_event.h>
#include <string.h>
#include "probe-event.h"
#include "debug.h"
@@ -13,6 +14,7 @@
#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
+ const char *obj_name,
int fd, void *arg);
#ifdef HAVE_LIBBPF_SUPPORT
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 3bedf64..21a11c9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -195,7 +195,45 @@ error:
return -ENOMEM;
}
-static int add_bpf_event(struct probe_trace_event *tev, int fd,
+static void
+sync_with_dummy(struct perf_evlist *evlist, const char *obj_name,
+ struct list_head *list)
+{
+ struct perf_evsel *dummy_evsel, *pos;
+ const char *filter;
+ bool found = false;
+ int err;
+
+ evlist__for_each(evlist, dummy_evsel) {
+ if (!perf_evsel__is_dummy(dummy_evsel))
+ continue;
+
+ if (strcmp(dummy_evsel->name, obj_name) == 0) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ pr_debug("Failed to find dummy event of '%s'\n",
+ obj_name);
+ return;
+ }
+
+ filter = dummy_evsel->filter;
+ if (!filter)
+ return;
+
+ list_for_each_entry(pos, list, node) {
+ err = perf_evsel__set_filter(pos, filter);
+ if (err)
+ pr_debug("Failed to set filter '%s' to evsel %s\n",
+ filter, pos->name);
+ }
+}
+
+static int add_bpf_event(struct probe_trace_event *tev,
+ const char *obj_name, int fd,
void *arg)
{
struct perf_evlist *evlist = arg;
@@ -203,8 +241,8 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
struct list_head list;
int err, idx, entries;
- pr_debug("add bpf event %s:%s and attach bpf program %d\n",
- tev->group, tev->event, fd);
+ pr_debug("add bpf event %s:%s and attach bpf program %d (from %s)\n",
+ tev->group, tev->event, fd, obj_name);
INIT_LIST_HEAD(&list);
idx = evlist->nr_entries;
@@ -226,6 +264,15 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
list_for_each_entry(pos, &list, node)
pos->bpf_fd = fd;
entries = idx - evlist->nr_entries;
+
+ sync_with_dummy(evlist, obj_name, &list);
+
+ /*
+ * Currectly we don't need to link those new events at the
+ * same place where dummy node reside because order of
+ * events in cmdline won't be used after
+ * 'perf_evlist__add_bpf'.
+ */
perf_evlist__splice_list_tail(evlist, &list, entries);
return 0;
}
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 27/32] perf tools: Use same BPF program if arguments are identical |
| Message-ID | <q2m79-4Ey-33@gated-at.bofh.it> |
| In reply to | #1215170 |
This patch allows creating only one BPF program for different
'probe_trace_event'(tev) generated by one 'perf_probe_event'(pev), if
their prologues are identical.
This is done by comparing argument list of different tev, and maps type
of prologue and tev using a mapping array. This patch utilizes qsort to
sort tevs. After sorting, tevs with identical argument list will group
together.
Signed-off-by: Wang Nan <wangnan0@hauwei.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/n/1436445342-1402-37-git-send-email-wangnan0@huawei.com
---
tools/perf/util/bpf-loader.c | 133 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 126 insertions(+), 7 deletions(-)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 66d9bea..a23aaf0 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -47,6 +47,8 @@ struct bpf_prog_priv {
};
bool need_prologue;
struct bpf_insn *insns_buf;
+ int nr_types;
+ int *type_mapping;
};
static void
@@ -59,6 +61,7 @@ bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused,
if (priv && priv->pev_ready)
clear_perf_probe_event(&priv->pev);
zfree(&priv->insns_buf);
+ zfree(&priv->type_mapping);
free(priv);
}
@@ -255,7 +258,7 @@ preproc_gen_prologue(struct bpf_program *prog, int n,
struct bpf_prog_priv *priv;
struct bpf_insn *buf;
size_t prologue_cnt = 0;
- int err;
+ int i, err;
err = bpf_program__get_private(prog, (void **)&priv);
if (err || !priv || !priv->pev_ready)
@@ -263,10 +266,20 @@ preproc_gen_prologue(struct bpf_program *prog, int n,
pev = &priv->pev;
- if (n < 0 || n >= pev->ntevs)
+ if (n < 0 || n >= priv->nr_types)
goto errout;
- tev = &pev->tevs[n];
+ /* Find a tev belongs to that type */
+ for (i = 0; i < pev->ntevs; i++)
+ if (priv->type_mapping[i] == n)
+ break;
+
+ if (i >= pev->ntevs) {
+ pr_debug("Internal error: prologue type %d not found\n", n);
+ return -ENOENT;
+ }
+
+ tev = &pev->tevs[i];
buf = priv->insns_buf;
err = bpf__gen_prologue(tev->args, tev->nargs,
@@ -297,6 +310,98 @@ errout:
return -EINVAL;
}
+/*
+ * compare_tev_args is reflexive, transitive and antisymmetric.
+ * I can show that but this margin is too narrow to contain.
+ */
+static int compare_tev_args(const void *ptev1, const void *ptev2)
+{
+ int i, ret;
+ const struct probe_trace_event *tev1 =
+ *(const struct probe_trace_event **)ptev1;
+ const struct probe_trace_event *tev2 =
+ *(const struct probe_trace_event **)ptev2;
+
+ ret = tev2->nargs - tev1->nargs;
+ if (ret)
+ return ret;
+
+ for (i = 0; i < tev1->nargs; i++) {
+ struct probe_trace_arg *arg1, *arg2;
+ struct probe_trace_arg_ref *ref1, *ref2;
+
+ arg1 = &tev1->args[i];
+ arg2 = &tev2->args[i];
+
+ ret = strcmp(arg1->value, arg2->value);
+ if (ret)
+ return ret;
+
+ ref1 = arg1->ref;
+ ref2 = arg2->ref;
+
+ while (ref1 && ref2) {
+ ret = ref2->offset - ref1->offset;
+ if (ret)
+ return ret;
+
+ ref1 = ref1->next;
+ ref2 = ref2->next;
+ }
+
+ if (ref1 || ref2)
+ return ref2 ? 1 : -1;
+ }
+
+ return 0;
+}
+
+static int map_prologue(struct perf_probe_event *pev, int *mapping,
+ int *nr_types)
+{
+ int i, type = 0;
+ struct {
+ struct probe_trace_event *tev;
+ int idx;
+ } *stevs;
+ size_t array_sz = sizeof(*stevs) * pev->ntevs;
+
+ stevs = malloc(array_sz);
+ if (!stevs) {
+ pr_debug("No ehough memory: alloc stevs failed\n");
+ return -ENOMEM;
+ }
+
+ pr_debug("In map_prologue, ntevs=%d\n", pev->ntevs);
+ for (i = 0; i < pev->ntevs; i++) {
+ stevs[i].tev = &pev->tevs[i];
+ stevs[i].idx = i;
+ }
+ qsort(stevs, pev->ntevs, sizeof(*stevs),
+ compare_tev_args);
+
+ for (i = 0; i < pev->ntevs; i++) {
+ if (i == 0) {
+ mapping[stevs[i].idx] = type;
+ pr_debug("mapping[%d]=%d\n", stevs[i].idx,
+ type);
+ continue;
+ }
+
+ if (compare_tev_args(stevs + i, stevs + i - 1) == 0)
+ mapping[stevs[i].idx] = type;
+ else
+ mapping[stevs[i].idx] = ++type;
+
+ pr_debug("mapping[%d]=%d\n", stevs[i].idx,
+ mapping[stevs[i].idx]);
+ }
+ free(stevs);
+ *nr_types = type + 1;
+
+ return 0;
+}
+
static int hook_load_preprocessor(struct bpf_program *prog)
{
struct perf_probe_event *pev;
@@ -337,7 +442,19 @@ static int hook_load_preprocessor(struct bpf_program *prog)
return -ENOMEM;
}
- err = bpf_program__set_prep(prog, pev->ntevs,
+ priv->type_mapping = malloc(sizeof(int) * pev->ntevs);
+ if (!priv->type_mapping) {
+ pr_debug("No enough memory: alloc type_mapping failed\n");
+ return -ENOMEM;
+ }
+ memset(priv->type_mapping, 0xff,
+ sizeof(int) * pev->ntevs);
+
+ err = map_prologue(pev, priv->type_mapping, &priv->nr_types);
+ if (err)
+ return err;
+
+ err = bpf_program__set_prep(prog, priv->nr_types,
preproc_gen_prologue);
return err;
}
@@ -463,9 +580,11 @@ int bpf__foreach_tev(bpf_prog_iter_callback_t func, void *arg)
for (i = 0; i < pev->ntevs; i++) {
tev = &pev->tevs[i];
- if (priv->need_prologue)
- fd = bpf_program__nth_fd(prog, i);
- else
+ if (priv->need_prologue) {
+ int type = priv->type_mapping[i];
+
+ fd = bpf_program__nth_fd(prog, type);
+ } else
fd = bpf_program__fd(prog);
if (fd < 0) {
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 04/32] perf tools: Make perf depend on libbpf |
| Message-ID | <q2m79-4Ey-35@gated-at.bofh.it> |
| In reply to | #1215170 |
By adding libbpf into perf's Makefile, this patch enables perf to build
libbpf during building if libelf is found and neither NO_LIBELF nor
NO_LIBBPF is set. The newly introduced code is similar to libapi and
libtraceevent building in Makefile.perf.
MANIFEST is also updated for 'make perf-*-src-pkg'.
Append make_no_libbpf to tools/perf/tests/make.
'bpf' feature check is appended into default FEATURE_TESTS and
FEATURE_DISPLAY, so perf will check API version of bpf in
/path/to/kernel/include/uapi/linux/bpf.h. Which should not fail except
when we are trying to port this code to an old kernel.
Error messages are also updated to notify users about the disable of BPF
support of 'perf record' if libelf is missed or BPF API check failed.
tools/lib/bpf is added into TAG_FOLDERS to allow us to navigate on
libbpf files when working on perf using tools/perf/tags.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1435716878-189507-24-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/build/Makefile.feature | 6 ++++--
tools/perf/MANIFEST | 3 +++
tools/perf/Makefile.perf | 19 +++++++++++++++++--
tools/perf/config/Makefile | 19 ++++++++++++++++++-
tools/perf/tests/make | 4 +++-
5 files changed, 45 insertions(+), 6 deletions(-)
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 2975632..5ec6b37 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -51,7 +51,8 @@ FEATURE_TESTS ?= \
timerfd \
libdw-dwarf-unwind \
zlib \
- lzma
+ lzma \
+ bpf
FEATURE_DISPLAY ?= \
dwarf \
@@ -67,7 +68,8 @@ FEATURE_DISPLAY ?= \
libunwind \
libdw-dwarf-unwind \
zlib \
- lzma
+ lzma \
+ bpf
# Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
# If in the future we need per-feature checks/flags for features not
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index af009bd..56fe0c9 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -17,6 +17,7 @@ tools/build
tools/arch/x86/include/asm/atomic.h
tools/arch/x86/include/asm/rmwcc.h
tools/lib/traceevent
+tools/lib/bpf
tools/lib/api
tools/lib/bpf
tools/lib/hweight.c
@@ -67,6 +68,8 @@ arch/*/lib/memset*.S
include/linux/poison.h
include/linux/hw_breakpoint.h
include/uapi/linux/perf_event.h
+include/uapi/linux/bpf.h
+include/uapi/linux/bpf_common.h
include/uapi/linux/const.h
include/uapi/linux/swab.h
include/uapi/linux/hw_breakpoint.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d9863cb..a6a789e 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -145,6 +145,7 @@ AWK = awk
LIB_DIR = $(srctree)/tools/lib/api/
TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
+BPF_DIR = $(srctree)/tools/lib/bpf/
# include config/Makefile by default and rule out
# non-config cases
@@ -180,6 +181,7 @@ strip-libs = $(filter-out -l%,$(1))
ifneq ($(OUTPUT),)
TE_PATH=$(OUTPUT)
+ BPF_PATH=$(OUTPUT)
ifneq ($(subdir),)
LIB_PATH=$(OUTPUT)/../lib/api/
else
@@ -188,6 +190,7 @@ endif
else
TE_PATH=$(TRACE_EVENT_DIR)
LIB_PATH=$(LIB_DIR)
+ BPF_PATH=$(BPF_DIR)
endif
LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
@@ -199,6 +202,8 @@ LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYN
LIBAPI = $(LIB_PATH)libapi.a
export LIBAPI
+LIBBPF = $(BPF_PATH)libbpf.a
+
# python extension build directories
PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
@@ -251,6 +256,9 @@ export PERL_PATH
LIB_FILE=$(OUTPUT)libperf.a
PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT)
+ifndef NO_LIBBPF
+ PERFLIBS += $(LIBBPF)
+endif
# We choose to avoid "if .. else if .. else .. endif endif"
# because maintaining the nesting to match is a pain. If
@@ -420,6 +428,13 @@ $(LIBAPI)-clean:
$(call QUIET_CLEAN, libapi)
$(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
+$(LIBBPF): FORCE
+ $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a
+
+$(LIBBPF)-clean:
+ $(call QUIET_CLEAN, libbpf)
+ $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null
+
help:
@echo 'Perf make targets:'
@echo ' doc - make *all* documentation (see below)'
@@ -459,7 +474,7 @@ INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
$(DOC_TARGETS):
$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
-TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol
+TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol ../lib/bpf
TAG_FILES= ../../include/uapi/linux/perf_event.h
TAGS:
@@ -567,7 +582,7 @@ config-clean:
$(call QUIET_CLEAN, config)
$(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null
-clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean
+clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean config-clean
$(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
$(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
$(Q)$(RM) $(OUTPUT).config-detected
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 827557f..38a4144 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -106,6 +106,7 @@ ifdef LIBBABELTRACE
FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
endif
+FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi
# include ARCH specific config
-include $(src-perf)/arch/$(ARCH)/Makefile
@@ -233,6 +234,7 @@ ifdef NO_LIBELF
NO_DEMANGLE := 1
NO_LIBUNWIND := 1
NO_LIBDW_DWARF_UNWIND := 1
+ NO_LIBBPF := 1
else
ifeq ($(feature-libelf), 0)
ifeq ($(feature-glibc), 1)
@@ -242,13 +244,14 @@ else
LIBC_SUPPORT := 1
endif
ifeq ($(LIBC_SUPPORT),1)
- msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev);
+ msg := $(warning No libelf found, disables 'probe' tool and BPF support in 'perf record', please install elfutils-libelf-devel/libelf-dev);
NO_LIBELF := 1
NO_DWARF := 1
NO_DEMANGLE := 1
NO_LIBUNWIND := 1
NO_LIBDW_DWARF_UNWIND := 1
+ NO_LIBBPF := 1
else
ifneq ($(filter s% -static%,$(LDFLAGS),),)
msg := $(error No static glibc found, please install glibc-static);
@@ -305,6 +308,13 @@ ifndef NO_LIBELF
$(call detected,CONFIG_DWARF)
endif # PERF_HAVE_DWARF_REGS
endif # NO_DWARF
+
+ ifndef NO_LIBBPF
+ ifeq ($(feature-bpf), 1)
+ CFLAGS += -DHAVE_LIBBPF_SUPPORT
+ $(call detected,CONFIG_LIBBPF)
+ endif
+ endif # NO_LIBBPF
endif # NO_LIBELF
ifeq ($(ARCH),powerpc)
@@ -320,6 +330,13 @@ ifndef NO_LIBUNWIND
endif
endif
+ifndef NO_LIBBPF
+ ifneq ($(feature-bpf), 1)
+ msg := $(warning BPF API too old. Please install recent kernel headers. BPF support in 'perf record' is disabled.)
+ NO_LIBBPF := 1
+ endif
+endif
+
dwarf-post-unwind := 1
dwarf-post-unwind-text := BUG
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index ba31c4b..2cbd0c6 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -44,6 +44,7 @@ make_no_libnuma := NO_LIBNUMA=1
make_no_libaudit := NO_LIBAUDIT=1
make_no_libbionic := NO_LIBBIONIC=1
make_no_auxtrace := NO_AUXTRACE=1
+make_no_libbpf := NO_LIBBPF=1
make_tags := tags
make_cscope := cscope
make_help := help
@@ -66,7 +67,7 @@ make_static := LDFLAGS=-static
make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
-make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1
+make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
# $(run) contains all available tests
run := make_pure
@@ -94,6 +95,7 @@ run += make_no_libnuma
run += make_no_libaudit
run += make_no_libbionic
run += make_no_auxtrace
+run += make_no_libbpf
run += make_help
run += make_doc
run += make_perf_o
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 09/32] perf bpf: Collect 'struct perf_probe_event' for bpf_program |
| Message-ID | <q2m79-4Ey-39@gated-at.bofh.it> |
| In reply to | #1215170 |
This patch utilizes bpf_program__set_private(), binding perf_probe_event
with bpf program by private field.
Saving those information so 'perf record' knows which kprobe point a program
should be attached.
Since data in 'struct perf_probe_event' is build by 2 stages, tev_ready
is used to mark whether the information (especially tevs) in 'struct
perf_probe_event' is valid or not. It is false at first, and set to true
by sync_bpf_program_pev(), which copy all pointers in original pev into
a program specific memory region. sync_bpf_program_pev() is called after
add_perf_probe_events() to make sure ready of data.
Remove code which clean 'struct perf_probe_event' after bpf__probe()
because pointers in pevs are copied to program's private field, calling
clear_perf_probe_event() becomes unsafe.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/n/1436445342-1402-21-git-send-email-wangnan0@huawei.com
[Splitted from a larger patch]
---
tools/perf/util/bpf-loader.c | 90 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 88 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 435f52e..ae23f6f 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -30,9 +30,35 @@ DEFINE_PRINT_FN(debug, 1)
static bool libbpf_initialized;
+struct bpf_prog_priv {
+ /*
+ * If pev_ready is false, ppev pointes to a local memory which
+ * is only valid inside bpf__probe().
+ * pev is valid only when pev_ready.
+ */
+ bool pev_ready;
+ union {
+ struct perf_probe_event *ppev;
+ struct perf_probe_event pev;
+ };
+};
+
+static void
+bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused,
+ void *_priv)
+{
+ struct bpf_prog_priv *priv = _priv;
+
+ /* check if pev is initialized */
+ if (priv && priv->pev_ready)
+ clear_perf_probe_event(&priv->pev);
+ free(priv);
+}
+
static int
config_bpf_program(struct bpf_program *prog, struct perf_probe_event *pev)
{
+ struct bpf_prog_priv *priv = NULL;
const char *config_str;
int err;
@@ -74,14 +100,58 @@ config_bpf_program(struct bpf_program *prog, struct perf_probe_event *pev)
pr_debug("bpf: config '%s' is ok\n", config_str);
+ priv = calloc(1, sizeof(*priv));
+ if (!priv) {
+ pr_debug("bpf: failed to alloc memory\n");
+ err = -ENOMEM;
+ goto errout;
+ }
+
+ /*
+ * At this very early stage, tevs inside pev are not ready.
+ * It becomes usable after add_perf_probe_events() is called.
+ * set pev_ready to false so further access read priv->ppev
+ * only.
+ */
+ priv->pev_ready = false;
+ priv->ppev = pev;
+
+ err = bpf_program__set_private(prog, priv,
+ bpf_prog_priv__clear);
+ if (err) {
+ pr_debug("bpf: set program private failed\n");
+ err = -ENOMEM;
+ goto errout;
+ }
return 0;
errout:
if (pev)
clear_perf_probe_event(pev);
+ if (priv)
+ free(priv);
return err;
}
+static int
+sync_bpf_program_pev(struct bpf_program *prog)
+{
+ int err;
+ struct bpf_prog_priv *priv;
+ struct perf_probe_event *ppev;
+
+ err = bpf_program__get_private(prog, (void **)&priv);
+ if (err || !priv || priv->pev_ready) {
+ pr_debug("Internal error: sync_bpf_program_pev\n");
+ return -EINVAL;
+ }
+
+ ppev = priv->ppev;
+ memcpy(&priv->pev, ppev, sizeof(*ppev));
+ priv->pev_ready = true;
+ return 0;
+}
+
int bpf__prepare_load(const char *filename)
{
struct bpf_object *obj;
@@ -172,11 +242,27 @@ int bpf__probe(void)
/* add_perf_probe_events return negative when fail */
if (err < 0) {
pr_debug("bpf probe: failed to probe events\n");
+ goto out;
} else
is_probed = true;
+
+ /*
+ * After add_perf_probe_events, 'struct perf_probe_event' is ready.
+ * Until now copying program's priv->pev field and freeing
+ * the big array allocated before become safe.
+ */
+ bpf_object__for_each_safe(obj, tmp) {
+ bpf_object__for_each_program(prog, obj) {
+ err = sync_bpf_program_pev(prog);
+ if (err)
+ goto out;
+ }
+ }
out:
- while (nr_events > 0)
- clear_perf_probe_event(&pevs[--nr_events]);
+ /*
+ * Don't call clear_perf_probe_event() for entries of pevs:
+ * they are used by prog's private field.
+ */
free(pevs);
return err < 0 ? err : 0;
}
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 21/32] perf probe: Reset args and nargs for probe_trace_event when failure |
| Message-ID | <q2m79-4Ey-43@gated-at.bofh.it> |
| In reply to | #1215170 |
When failure occures in add_probe_trace_event(), args in
probe_trace_event is incomplete. Since information in it may be used
in further, this patch frees the allocated memory and set it to NULL
to avoid dangling pointer.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/n/1436445342-1402-31-git-send-email-wangnan0@huawei.com
---
tools/perf/util/probe-finder.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 29c43c068..5ab9cd6 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1228,6 +1228,10 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
end:
free(args);
+ if (ret) {
+ tev->nargs = 0;
+ zfree(&tev->args);
+ }
return ret;
}
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 16/32] perf tools: Infrastructure for compiling scriptlets when passing '.c' to --event |
| Message-ID | <q2m79-4Ey-49@gated-at.bofh.it> |
| In reply to | #1215170 |
This patch provides infrastructure for passing source files to --event
directly using:
# perf record --event bpf-file.c command
This patch does following works:
1) Allow passing '.c' file to '--event'. parse_events_load_bpf() is
expanded to allow caller tell it whether the passed file is source
file or object.
2) llvm__compile_bpf() is called to compile the '.c' file, the result
is saved into memory. Use bpf_object__open_buffer() to load the
in-memory object.
Introduces a bpf-script-example.c so we can manually test it:
# perf record --clang-opt "-DLINUX_VERSION_CODE=0x40200" --event ./bpf-script-example.c sleep 1
Note that '--clang-opt' must put before '--event'.
Futher patches will merge it into a testcase so can be tested automatically.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/n/1436445342-1402-20-git-send-email-wangnan0@huawei.com
[ wangnan: Pass name of source file to bpf_object__open_buffer(). ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/tests/bpf-script-example.c | 44 +++++++++++++++++++++++++++++++++++
tools/perf/util/bpf-loader.c | 25 +++++++++++++++-----
tools/perf/util/bpf-loader.h | 10 ++++----
tools/perf/util/parse-events.c | 8 +++----
tools/perf/util/parse-events.h | 3 ++-
tools/perf/util/parse-events.l | 3 +++
tools/perf/util/parse-events.y | 15 ++++++++++--
7 files changed, 91 insertions(+), 17 deletions(-)
create mode 100644 tools/perf/tests/bpf-script-example.c
diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
new file mode 100644
index 0000000..410a70b
--- /dev/null
+++ b/tools/perf/tests/bpf-script-example.c
@@ -0,0 +1,44 @@
+#ifndef LINUX_VERSION_CODE
+# 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 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;
+ unsigned int key_size;
+ unsigned int value_size;
+ unsigned int max_entries;
+};
+
+#define SEC(NAME) __attribute__((section(NAME), used))
+struct bpf_map_def SEC("maps") flip_table = {
+ .type = BPF_MAP_TYPE_ARRAY,
+ .key_size = sizeof(int),
+ .value_size = sizeof(int),
+ .max_entries = 1,
+};
+
+SEC("func=sys_epoll_pwait")
+int bpf_func__sys_epoll_pwait(void *ctx)
+{
+ int ind =0;
+ int *flag = bpf_map_lookup_elem(&flip_table, &ind);
+ int new_flag;
+ if (!flag)
+ return 0;
+ /* flip flag and store back */
+ new_flag = !*flag;
+ bpf_map_update_elem(&flip_table, &ind, &new_flag, BPF_ANY);
+ return new_flag;
+}
+char _license[] SEC("license") = "GPL";
+int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 77eeb99..c2aafe2 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -11,6 +11,7 @@
#include "bpf-loader.h"
#include "probe-event.h"
#include "probe-finder.h"
+#include "llvm-utils.h"
#define DEFINE_PRINT_FN(name, level) \
static int libbpf_##name(const char *fmt, ...) \
@@ -152,16 +153,28 @@ sync_bpf_program_pev(struct bpf_program *prog)
return 0;
}
-int bpf__prepare_load(const char *filename)
+int bpf__prepare_load(const char *filename, bool source)
{
struct bpf_object *obj;
+ int err;
if (!libbpf_initialized)
libbpf_set_print(libbpf_warning,
libbpf_info,
libbpf_debug);
- obj = bpf_object__open(filename);
+ if (source) {
+ void *obj_buf;
+ size_t obj_buf_sz;
+
+ err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+ if (err)
+ return err;
+ obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
+ free(obj_buf);
+ } else
+ obj = bpf_object__open(filename);
+
if (!obj) {
pr_debug("bpf: failed to load %s\n", filename);
return -EINVAL;
@@ -361,12 +374,12 @@ int bpf__foreach_tev(bpf_prog_iter_callback_t func, void *arg)
}\
buf[size - 1] = '\0';
-int bpf__strerror_prepare_load(const char *filename, int err,
- char *buf, size_t size)
+int bpf__strerror_prepare_load(const char *filename, bool source,
+ int err, char *buf, size_t size)
{
bpf__strerror_head(err, buf, size);
- bpf__strerror_entry(EINVAL, "%s: BPF object file '%s' is invalid",
- emsg, filename)
+ bpf__strerror_entry(EINVAL, "%s: BPF %s file '%s' is invalid",
+ emsg, source ? "source" : "object", filename);
bpf__strerror_end(buf, size);
return 0;
}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 323e664..97aed65 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -18,9 +18,9 @@ typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
int fd, void *arg);
#ifdef HAVE_LIBBPF_SUPPORT
-int bpf__prepare_load(const char *filename);
-int bpf__strerror_prepare_load(const char *filename, int err,
- char *buf, size_t size);
+int bpf__prepare_load(const char *filename, bool source);
+int bpf__strerror_prepare_load(const char *filename, bool source,
+ int err, char *buf, size_t size);
int bpf__probe(void);
int bpf__unprobe(void);
int bpf__strerror_probe(int err, char *buf, size_t size);
@@ -32,7 +32,8 @@ void bpf__clear(void);
int bpf__foreach_tev(bpf_prog_iter_callback_t func, void *arg);
#else
-static inline int bpf__prepare_load(const char *filename __maybe_unused)
+static inline int bpf__prepare_load(const char *filename __maybe_unused,
+ bool source __maybe_unused)
{
pr_debug("ERROR: eBPF object loading is disabled during compiling.\n");
return -1;
@@ -64,6 +65,7 @@ __bpf_strerror(char *buf, size_t size)
static inline int
bpf__strerror_prepare_load(const char *filename __maybe_unused,
+ bool source __maybe_unused,
int err __maybe_unused,
char *buf, size_t size)
{
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4343433..08b277b 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -483,8 +483,8 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
}
int parse_events_load_bpf(struct parse_events_evlist *data,
- struct list_head *list,
- char *bpf_file_name)
+ struct list_head *list __maybe_unused,
+ char *bpf_file_name, bool source)
{
int err;
char errbuf[BUFSIZ];
@@ -500,9 +500,9 @@ int parse_events_load_bpf(struct parse_events_evlist *data,
* problem. After that probe events file by file is possible.
* However, probing cost is still need to be considered.
*/
- err = bpf__prepare_load(bpf_file_name);
+ err = bpf__prepare_load(bpf_file_name, source);
if (err) {
- bpf__strerror_prepare_load(bpf_file_name, err,
+ bpf__strerror_prepare_load(bpf_file_name, source, err,
errbuf, sizeof(errbuf));
data->error->str = strdup(errbuf);
data->error->help = strdup("(add -v to see detail)");
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 3652387..728a424 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -121,7 +121,8 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
char *sys, char *event);
int parse_events_load_bpf(struct parse_events_evlist *data,
struct list_head *list,
- char *bpf_file_name);
+ char *bpf_file_name,
+ bool source);
int parse_events_add_numeric(struct parse_events_evlist *data,
struct list_head *list,
u32 type, u64 config,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 22e8f93..8033890 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -116,6 +116,7 @@ group [^,{}/]*[{][^}]*[}][^,{}/]*
event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
event [^,{}/]+
bpf_object .*\.(o|bpf)
+bpf_source .*\.c
num_dec [0-9]+
num_hex 0x[a-fA-F0-9]+
@@ -161,6 +162,7 @@ modifier_bp [rwx]{1,3}
{event_pmu} |
{bpf_object} |
+{bpf_source} |
{event} {
BEGIN(INITIAL);
REWIND(1);
@@ -267,6 +269,7 @@ r{num_raw_hex} { return raw(yyscanner); }
{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
{bpf_object} { return str(yyscanner, PE_BPF_OBJECT); }
+{bpf_source} { return str(yyscanner, PE_BPF_SOURCE); }
{name} { return pmu_str_check(yyscanner); }
"/" { BEGIN(config); return '/'; }
- { return '-'; }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 3ee3a32..90d2458 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -42,7 +42,7 @@ static inc_group_count(struct list_head *list,
%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
%token PE_EVENT_NAME
%token PE_NAME
-%token PE_BPF_OBJECT
+%token PE_BPF_OBJECT PE_BPF_SOURCE
%token PE_MODIFIER_EVENT PE_MODIFIER_BP
%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
@@ -55,6 +55,7 @@ static inc_group_count(struct list_head *list,
%type <num> PE_TERM
%type <str> PE_NAME
%type <str> PE_BPF_OBJECT
+%type <str> PE_BPF_SOURCE
%type <str> PE_NAME_CACHE_TYPE
%type <str> PE_NAME_CACHE_OP_RESULT
%type <str> PE_MODIFIER_EVENT
@@ -431,7 +432,17 @@ PE_BPF_OBJECT
struct list_head *list;
ALLOC_LIST(list);
- ABORT_ON(parse_events_load_bpf(data, list, $1));
+ ABORT_ON(parse_events_load_bpf(data, list, $1, false));
+ $$ = list;
+}
+|
+PE_BPF_SOURCE
+{
+ struct parse_events_evlist *data = _data;
+ struct list_head *list;
+
+ ALLOC_LIST(list);
+ ABORT_ON(parse_events_load_bpf(data, list, $1, true));
$$ = list;
}
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 24/32] perf tools: Introduce arch_get_reg_info() for x86 |
| Message-ID | <q2m79-4Ey-47@gated-at.bofh.it> |
| In reply to | #1215170 |
From: He Kuang <hekuang@huawei.com>
arch_get_reg_info() is a helper function which converts register name
like "%rax" to offset of a register in 'struct pt_regs', which is
required by BPF prologue generator.
This patch replaces original string table by a 'struct reg_info' table,
which records offset of registers according to its name.
For x86, since there are two sub-archs (x86_32 and x86_64) but we can
only get pt_regs for the arch we are currently on, this patch fills
offset with '-1' for another sub-arch. This introduces a limitation to
perf prologue that, we are unable to generate prologue on a x86_32
compiled perf for BPF programs targeted on x86_64 kernel. This
limitation is acceptable, because this is a very rare usecase.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/n/1436445342-1402-34-git-send-email-wangnan0@huawei.com
---
tools/perf/arch/x86/Makefile | 1 +
tools/perf/arch/x86/util/Build | 2 +
tools/perf/arch/x86/util/dwarf-regs.c | 104 ++++++++++++++++++++++++----------
3 files changed, 78 insertions(+), 29 deletions(-)
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 21322e0..a84a6f6f 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -2,3 +2,4 @@ ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1
endif
HAVE_KVM_STAT_SUPPORT := 1
+PERF_HAVE_ARCH_GET_REG_INFO := 1
diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build
index 2c55e1b..09429f6 100644
--- a/tools/perf/arch/x86/util/Build
+++ b/tools/perf/arch/x86/util/Build
@@ -3,6 +3,8 @@ libperf-y += tsc.o
libperf-y += pmu.o
libperf-y += kvm-stat.o
+# BPF_PROLOGUE also need dwarf-regs.o. However, if CONFIG_BPF_PROLOGUE
+# is true, CONFIG_DWARF must true.
libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
diff --git a/tools/perf/arch/x86/util/dwarf-regs.c b/tools/perf/arch/x86/util/dwarf-regs.c
index be22dd4..9928caf 100644
--- a/tools/perf/arch/x86/util/dwarf-regs.c
+++ b/tools/perf/arch/x86/util/dwarf-regs.c
@@ -22,44 +22,67 @@
#include <stddef.h>
#include <dwarf-regs.h>
+#include <string.h>
+#include <linux/ptrace.h>
+#include <linux/kernel.h> /* for offsetof */
+#include <util/bpf-loader.h>
+
+struct reg_info {
+ const char *name; /* Reg string in debuginfo */
+ int offset; /* Reg offset in struct pt_regs */
+};
/*
* Generic dwarf analysis helpers
*/
-
+/*
+ * x86_64 compiling can't access pt_regs for x86_32, so fill offset
+ * with -1.
+ */
+#ifdef __x86_64__
+# define REG_INFO(n, f) { .name = n, .offset = -1, }
+#else
+# define REG_INFO(n, f) { .name = n, .offset = offsetof(struct pt_regs, f), }
+#endif
#define X86_32_MAX_REGS 8
-const char *x86_32_regs_table[X86_32_MAX_REGS] = {
- "%ax",
- "%cx",
- "%dx",
- "%bx",
- "$stack", /* Stack address instead of %sp */
- "%bp",
- "%si",
- "%di",
+
+struct reg_info x86_32_regs_table[X86_32_MAX_REGS] = {
+ REG_INFO("%ax", eax),
+ REG_INFO("%cx", ecx),
+ REG_INFO("%dx", edx),
+ REG_INFO("%bx", ebx),
+ REG_INFO("$stack", esp), /* Stack address instead of %sp */
+ REG_INFO("%bp", ebp),
+ REG_INFO("%si", esi),
+ REG_INFO("%di", edi),
};
+#undef REG_INFO
+#ifdef __x86_64__
+# define REG_INFO(n, f) { .name = n, .offset = offsetof(struct pt_regs, f), }
+#else
+# define REG_INFO(n, f) { .name = n, .offset = -1, }
+#endif
#define X86_64_MAX_REGS 16
-const char *x86_64_regs_table[X86_64_MAX_REGS] = {
- "%ax",
- "%dx",
- "%cx",
- "%bx",
- "%si",
- "%di",
- "%bp",
- "%sp",
- "%r8",
- "%r9",
- "%r10",
- "%r11",
- "%r12",
- "%r13",
- "%r14",
- "%r15",
+struct reg_info x86_64_regs_table[X86_64_MAX_REGS] = {
+ REG_INFO("%ax", rax),
+ REG_INFO("%dx", rdx),
+ REG_INFO("%cx", rcx),
+ REG_INFO("%bx", rbx),
+ REG_INFO("%si", rsi),
+ REG_INFO("%di", rdi),
+ REG_INFO("%bp", rbp),
+ REG_INFO("%sp", rsp),
+ REG_INFO("%r8", r8),
+ REG_INFO("%r9", r9),
+ REG_INFO("%r10", r10),
+ REG_INFO("%r11", r11),
+ REG_INFO("%r12", r12),
+ REG_INFO("%r13", r13),
+ REG_INFO("%r14", r14),
+ REG_INFO("%r15", r15),
};
-/* TODO: switching by dwarf address size */
#ifdef __x86_64__
#define ARCH_MAX_REGS X86_64_MAX_REGS
#define arch_regs_table x86_64_regs_table
@@ -71,5 +94,28 @@ const char *x86_64_regs_table[X86_64_MAX_REGS] = {
/* Return architecture dependent register string (for kprobe-tracer) */
const char *get_arch_regstr(unsigned int n)
{
- return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
+ return (n <= ARCH_MAX_REGS) ? arch_regs_table[n].name : NULL;
}
+
+#ifdef HAVE_BPF_PROLOGUE
+int arch_get_reg_info(const char *name, int *offset)
+{
+ int i;
+ struct reg_info *info;
+
+ if (!name || !offset)
+ return -1;
+
+ for (i = 0; i < ARCH_MAX_REGS; i++) {
+ info = &arch_regs_table[i];
+ if (strcmp(info->name, name) == 0) {
+ if (info->offset < 0)
+ return -1;
+ *offset = info->offset;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+#endif
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 15/32] perf record: Add clang options for compiling BPF scripts |
| Message-ID | <q2m79-4Ey-53@gated-at.bofh.it> |
| In reply to | #1215170 |
Although previous patch allows setting BPF compiler related options in
perfconfig, on some ad-hoc situation it still requires passing options
through cmdline. This patch introduces 2 options to 'perf record' for
this propose: --clang-path and --clang-opt.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/n/1436445342-1402-28-git-send-email-wangnan0@huawei.com
---
tools/perf/builtin-record.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index fd56a5b..212718c 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -30,6 +30,7 @@
#include "util/auxtrace.h"
#include "util/parse-branch-options.h"
#include "util/bpf-loader.h"
+#include "util/llvm-utils.h"
#include <unistd.h>
#include <sched.h>
@@ -1094,6 +1095,12 @@ struct option __record_options[] = {
"per thread proc mmap processing timeout in ms"),
OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
"Record context switch events"),
+#ifdef HAVE_LIBBPF_SUPPORT
+ OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
+ "clang binary to use for compiling BPF scriptlets"),
+ OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
+ "options passed to clang when compiling BPF scriptlets"),
+#endif
OPT_END()
};
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 18/32] perf test: Add 'perf test BPF' |
| Message-ID | <q2m79-4Ey-45@gated-at.bofh.it> |
| In reply to | #1215170 |
This patch adds BPF testcase for testing BPF event filtering.
By utilizing the result of 'perf test LLVM', this patch compiles the
eBPF sample program then test it ability. The BPF script in 'perf test
LLVM' collects half of execution of epoll_pwait(). This patch runs 111
times of it, so the resule should contains 56 samples.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/n/1440151770-129878-16-git-send-email-wangnan0@huawei.com
---
tools/perf/tests/Build | 1 +
tools/perf/tests/bpf.c | 170 ++++++++++++++++++++++++++++++++++++++++
tools/perf/tests/builtin-test.c | 4 +
tools/perf/tests/llvm.c | 19 +++++
tools/perf/tests/llvm.h | 1 +
tools/perf/tests/tests.h | 1 +
tools/perf/util/bpf-loader.c | 14 ++++
tools/perf/util/bpf-loader.h | 8 ++
8 files changed, 218 insertions(+)
create mode 100644 tools/perf/tests/bpf.c
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 8c98409..7ceb448 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -33,6 +33,7 @@ perf-y += parse-no-sample-id-all.o
perf-y += kmod-path.o
perf-y += thread-map.o
perf-y += llvm.o llvm-src.o
+perf-y += bpf.o
$(OUTPUT)tests/llvm-src.c: tests/bpf-script-example.c
$(Q)echo '#include <tests/llvm.h>' > $@
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
new file mode 100644
index 0000000..6c238ca
--- /dev/null
+++ b/tools/perf/tests/bpf.c
@@ -0,0 +1,170 @@
+#include <stdio.h>
+#include <sys/epoll.h>
+#include <util/bpf-loader.h>
+#include <util/evlist.h>
+#include "tests.h"
+#include "llvm.h"
+#include "debug.h"
+#define NR_ITERS 111
+
+#ifdef HAVE_LIBBPF_SUPPORT
+
+static int epoll_pwait_loop(void)
+{
+ int i;
+
+ /* Should fail NR_ITERS times */
+ for (i = 0; i < NR_ITERS; i++)
+ epoll_pwait(-(i + 1), NULL, 0, 0, NULL);
+ return 0;
+}
+
+static int prepare_bpf(void *obj_buf, size_t obj_buf_sz)
+{
+ int err;
+ char errbuf[BUFSIZ];
+
+ err = bpf__prepare_load_buffer(obj_buf, obj_buf_sz, NULL);
+ if (err) {
+ bpf__strerror_prepare_load("[buffer]", false, err, errbuf,
+ sizeof(errbuf));
+ fprintf(stderr, " (%s)", errbuf);
+ return TEST_FAIL;
+ }
+
+ err = bpf__probe();
+ if (err) {
+ bpf__strerror_load(err, errbuf, sizeof(errbuf));
+ fprintf(stderr, " (%s)", errbuf);
+ if (getuid() != 0)
+ fprintf(stderr, " (try run as root)");
+ return TEST_FAIL;
+ }
+
+ err = bpf__load();
+ if (err) {
+ bpf__strerror_load(err, errbuf, sizeof(errbuf));
+ fprintf(stderr, " (%s)", errbuf);
+ return TEST_FAIL;
+ }
+
+ return 0;
+}
+
+static int do_test(void)
+{
+ struct record_opts opts = {
+ .target = {
+ .uid = UINT_MAX,
+ .uses_mmap = true,
+ },
+ .freq = 0,
+ .mmap_pages = 256,
+ .default_interval = 1,
+ };
+
+ int err, i, count = 0;
+ char pid[16];
+ char sbuf[STRERR_BUFSIZE];
+ struct perf_evlist *evlist;
+
+ snprintf(pid, sizeof(pid), "%d", getpid());
+ pid[sizeof(pid) - 1] = '\0';
+ opts.target.tid = opts.target.pid = pid;
+
+ /* Instead of perf_evlist__new_default, don't add default events */
+ evlist = perf_evlist__new();
+ if (!evlist) {
+ pr_debug("No ehough memory to create evlist\n");
+ return -ENOMEM;
+ }
+
+ err = perf_evlist__create_maps(evlist, &opts.target);
+ if (err < 0) {
+ pr_debug("Not enough memory to create thread/cpu maps\n");
+ goto out_delete_evlist;
+ }
+
+ err = perf_evlist__add_bpf(evlist);
+ if (err) {
+ fprintf(stderr, " (Failed to add events selected by BPF)");
+ goto out_delete_evlist;
+ }
+
+ perf_evlist__config(evlist, &opts);
+
+ err = perf_evlist__open(evlist);
+ if (err < 0) {
+ pr_debug("perf_evlist__open: %s\n",
+ strerror_r(errno, sbuf, sizeof(sbuf)));
+ goto out_delete_evlist;
+ }
+
+ err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
+ if (err < 0) {
+ pr_debug("perf_evlist__mmap: %s\n",
+ strerror_r(errno, sbuf, sizeof(sbuf)));
+ goto out_delete_evlist;
+ }
+
+ perf_evlist__enable(evlist);
+ epoll_pwait_loop();
+ perf_evlist__disable(evlist);
+
+ for (i = 0; i < evlist->nr_mmaps; i++) {
+ union perf_event *event;
+
+ while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
+ const u32 type = event->header.type;
+
+ if (type == PERF_RECORD_SAMPLE)
+ count ++;
+ }
+ }
+
+ if (count != (NR_ITERS + 1) / 2) {
+ fprintf(stderr, " (filter result incorrect)");
+ err = -EBADF;
+ }
+
+out_delete_evlist:
+ perf_evlist__delete(evlist);
+ if (err)
+ return TEST_FAIL;
+ return 0;
+}
+
+int test__bpf(void)
+{
+ int err;
+ void *obj_buf;
+ size_t obj_buf_sz;
+
+ test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz);
+ if (!obj_buf || !obj_buf_sz) {
+ if (verbose == 0)
+ fprintf(stderr, " (fix 'perf test LLVM' first)");
+ return TEST_SKIP;
+ }
+
+ err = prepare_bpf(obj_buf, obj_buf_sz);
+ if (err)
+ goto out;
+
+ err = do_test();
+ if (err)
+ goto out;
+out:
+ bpf__unprobe();
+ bpf__clear();
+ if (err)
+ return TEST_FAIL;
+ return 0;
+}
+
+#else
+int test__bpf(void)
+{
+ return TEST_SKIP;
+}
+#endif
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 1a349e8..c32c836 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -183,6 +183,10 @@ static struct test {
.cleanup = test__llvm_cleanup,
},
{
+ .desc = "Test BPF filter",
+ .func = test__bpf,
+ },
+ {
.func = NULL,
},
};
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index 236bf39..fd5fdb0 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -174,3 +174,22 @@ void test__llvm_cleanup(void)
(~((unsigned long)page_size - 1));
munmap((void *)boundary, buf_end - boundary);
}
+
+void
+test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz)
+{
+ *p_obj_buf = NULL;
+ *p_obj_buf_sz = 0;
+
+ if (!p_test_llvm__bpf_result) {
+ test__llvm_prepare();
+ test__llvm();
+ test__llvm_cleanup();
+ }
+
+ if (!p_test_llvm__bpf_result)
+ return;
+
+ *p_obj_buf = p_test_llvm__bpf_result->object;
+ *p_obj_buf_sz = p_test_llvm__bpf_result->size;
+}
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
index 1e89e46..2fd7ed6 100644
--- a/tools/perf/tests/llvm.h
+++ b/tools/perf/tests/llvm.h
@@ -10,5 +10,6 @@ struct test_llvm__bpf_result {
extern struct test_llvm__bpf_result *p_test_llvm__bpf_result;
extern const char test_llvm__bpf_prog[];
+void test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz);
#endif
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 0d79f04..f8ded73 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -65,6 +65,7 @@ int test__thread_map(void);
int test__llvm(void);
void test__llvm_prepare(void);
void test__llvm_cleanup(void);
+int test__bpf(void);
#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index c2aafe2..95e529b 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -153,6 +153,20 @@ sync_bpf_program_pev(struct bpf_program *prog)
return 0;
}
+int bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz,
+ const char *name)
+{
+ struct bpf_object *obj;
+
+ obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, name);
+ if (!obj) {
+ pr_debug("bpf: failed to load buffer\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
int bpf__prepare_load(const char *filename, bool source)
{
struct bpf_object *obj;
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 97aed65..dead4d4 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -19,6 +19,8 @@ typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
#ifdef HAVE_LIBBPF_SUPPORT
int bpf__prepare_load(const char *filename, bool source);
+int bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz,
+ const char *name);
int bpf__strerror_prepare_load(const char *filename, bool source,
int err, char *buf, size_t size);
int bpf__probe(void);
@@ -39,6 +41,12 @@ static inline int bpf__prepare_load(const char *filename __maybe_unused,
return -1;
}
+static inline int bpf__prepare_load_buffer(void *obj_buf __maybe_unused,
+ size_t obj_buf_sz __maybe_unused)
+{
+ return bpf__prepare_load(NULL, false);
+}
+
static inline int bpf__probe(void) { return 0; }
static inline int bpf__unprobe(void) { return 0; }
static inline int bpf__load(void) { return 0; }
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 19/32] bpf tools: Load a program with different instances using preprocessor |
| Message-ID | <q2m79-4Ey-51@gated-at.bofh.it> |
| In reply to | #1215170 |
In this patch, caller of libbpf is able to control the loaded programs
by installing a preprocessor callback for a BPF program. With
preprocessor, different instances can be created from one BPF program.
This patch will be used by perf to generate different prologue for
different 'struct probe_trace_event' instances matched by one
'struct perf_probe_event'.
bpf_program__set_prep() is added to support this feature. Caller
should pass libbpf the number of instances should be created and a
preprocessor function which will be called when doing real loading.
The callback should return instructions arrays for each instances.
fd field in bpf_programs is replaced by instance, which has an nr field
and fds array. bpf_program__nth_fd() is introduced for read fd of
instances. Old interface bpf_program__fd() is reimplemented by
returning the first fd.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/n/1436445342-1402-29-git-send-email-wangnan0@huawei.com
[wangnan: Add missing '!',
allows bpf_program__unload() when prog->instance.nr == -1
]
---
tools/lib/bpf/libbpf.c | 143 +++++++++++++++++++++++++++++++++++++++++++++----
tools/lib/bpf/libbpf.h | 22 ++++++++
2 files changed, 156 insertions(+), 9 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 4252fc2..6a07b26 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -98,7 +98,11 @@ struct bpf_program {
} *reloc_desc;
int nr_reloc;
- int fd;
+ struct {
+ int nr;
+ int *fds;
+ } instance;
+ bpf_program_prep_t preprocessor;
struct bpf_object *obj;
void *priv;
@@ -152,10 +156,24 @@ struct bpf_object {
static void bpf_program__unload(struct bpf_program *prog)
{
+ int i;
+
if (!prog)
return;
- zclose(prog->fd);
+ /*
+ * If the object is opened but the program is never loaded,
+ * it is possible that prog->instance.nr == -1.
+ */
+ if (prog->instance.nr > 0) {
+ for (i = 0; i < prog->instance.nr; i++)
+ zclose(prog->instance.fds[i]);
+ } else if (prog->instance.nr != -1)
+ pr_warning("Internal error: instance.nr is %d\n",
+ prog->instance.nr);
+
+ prog->instance.nr = -1;
+ zfree(&prog->instance.fds);
}
static void bpf_program__exit(struct bpf_program *prog)
@@ -206,7 +224,8 @@ bpf_program__init(void *data, size_t size, char *name, int idx,
memcpy(prog->insns, data,
prog->insns_cnt * sizeof(struct bpf_insn));
prog->idx = idx;
- prog->fd = -1;
+ prog->instance.fds = NULL;
+ prog->instance.nr = -1;
return 0;
errout:
@@ -795,13 +814,71 @@ static int
bpf_program__load(struct bpf_program *prog,
char *license, u32 kern_version)
{
- int err, fd;
+ int err = 0, fd, i;
+
+ if (prog->instance.nr < 0 || !prog->instance.fds) {
+ if (prog->preprocessor) {
+ pr_warning("Internal error: can't load program '%s'\n",
+ prog->section_name);
+ return -EINVAL;
+ }
+
+ prog->instance.fds = malloc(sizeof(int));
+ if (!prog->instance.fds) {
+ pr_warning("No enough memory for fds\n");
+ return -ENOMEM;
+ }
+ prog->instance.nr = 1;
+ prog->instance.fds[0] = -1;
+ }
+
+ if (!prog->preprocessor) {
+ if (prog->instance.nr != 1)
+ pr_warning("Program '%s' inconsistent: nr(%d) not 1\n",
+ prog->section_name, prog->instance.nr);
- err = load_program(prog->insns, prog->insns_cnt,
- license, kern_version, &fd);
- if (!err)
- prog->fd = fd;
+ err = load_program(prog->insns, prog->insns_cnt,
+ license, kern_version, &fd);
+ if (!err)
+ prog->instance.fds[0] = fd;
+ goto out;
+ }
+
+ for (i = 0; i < prog->instance.nr; i++) {
+ struct bpf_prog_prep_result result;
+ bpf_program_prep_t preprocessor = prog->preprocessor;
+
+ bzero(&result, sizeof(result));
+ err = preprocessor(prog, i, prog->insns,
+ prog->insns_cnt, &result);
+ if (err) {
+ pr_warning("Preprocessing %dth instance of program '%s' failed\n",
+ i, prog->section_name);
+ goto out;
+ }
+
+ if (!result.new_insn_ptr || !result.new_insn_cnt) {
+ pr_debug("Skip loading %dth instance of program '%s'\n",
+ i, prog->section_name);
+ prog->instance.fds[i] = -1;
+ continue;
+ }
+
+ err = load_program(result.new_insn_ptr,
+ result.new_insn_cnt,
+ license, kern_version, &fd);
+
+ if (err) {
+ pr_warning("Loading %dth instance of program '%s' failed\n",
+ i, prog->section_name);
+ goto out;
+ }
+ if (result.pfd)
+ *result.pfd = fd;
+ prog->instance.fds[i] = fd;
+ }
+out:
if (err)
pr_warning("failed to load program '%s'\n",
prog->section_name);
@@ -1052,5 +1129,53 @@ const char *bpf_program__title(struct bpf_program *prog, bool dup)
int bpf_program__fd(struct bpf_program *prog)
{
- return prog->fd;
+ return bpf_program__nth_fd(prog, 0);
+}
+
+int bpf_program__set_prep(struct bpf_program *prog, int nr_instance,
+ bpf_program_prep_t prep)
+{
+ int *instance_fds;
+
+ if (nr_instance <= 0 || !prep)
+ return -EINVAL;
+
+ if (prog->instance.nr > 0 || prog->instance.fds) {
+ pr_warning("Can't set pre-processor after loading\n");
+ return -EINVAL;
+ }
+
+ instance_fds = malloc(sizeof(int) * nr_instance);
+ if (!instance_fds) {
+ pr_warning("alloc memory failed for instance of fds\n");
+ return -ENOMEM;
+ }
+
+ /* fill all fd with -1 */
+ memset(instance_fds, 0xff, sizeof(int) * nr_instance);
+
+ prog->instance.nr = nr_instance;
+ prog->instance.fds = instance_fds;
+ prog->preprocessor = prep;
+ return 0;
+}
+
+int bpf_program__nth_fd(struct bpf_program *prog, int n)
+{
+ int fd;
+
+ if (n >= prog->instance.nr || n < 0) {
+ pr_warning("Can't get the %dth fd from program %s: only %d instances\n",
+ n, prog->section_name, prog->instance.nr);
+ return -EINVAL;
+ }
+
+ fd = prog->instance.fds[n];
+ if (fd < 0) {
+ pr_warning("%dth instance of program '%s' is invalid\n",
+ n, prog->section_name);
+ return -ENOENT;
+ }
+
+ return fd;
}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index f16170c..d82b89e 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -67,6 +67,28 @@ const char *bpf_program__title(struct bpf_program *prog, bool dup);
int bpf_program__fd(struct bpf_program *prog);
+struct bpf_insn;
+struct bpf_prog_prep_result {
+ /*
+ * If not NULL, load new instruction array.
+ * If set to NULL, don't load this instance.
+ */
+ struct bpf_insn *new_insn_ptr;
+ int new_insn_cnt;
+
+ /* If not NULL, result fd is set to it */
+ int *pfd;
+};
+
+typedef int (*bpf_program_prep_t)(struct bpf_program *, int n,
+ struct bpf_insn *, int insn_cnt,
+ struct bpf_prog_prep_result *res);
+
+int bpf_program__set_prep(struct bpf_program *prog, int nr_instance,
+ bpf_program_prep_t prep);
+
+int bpf_program__nth_fd(struct bpf_program *prog, int n);
+
/*
* We don't need __attribute__((packed)) now since it is
* unnecessary for 'bpf_map_def' because they are all aligned.
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 13/32] perf tools: Attach eBPF program to perf event |
| Message-ID | <q2m79-4Ey-55@gated-at.bofh.it> |
| In reply to | #1215170 |
This is the final patch which makes basic BPF filter work. After
applying this patch, users are allowed to use BPF filter like:
# perf record --event ./hello_world.c ls
In this patch PERF_EVENT_IOC_SET_BPF ioctl is used to attach eBPF
program to a newly created perf event. The file descriptor of the
eBPF program is passed to perf record using previous patches, and
stored into evsel->bpf_fd.
It is possible that different perf event are created for one kprobe
events for different CPUs. In this case, when trying to call the
ioctl, EEXIST will be return. This patch doesn't treat it as an error.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/n/1436445342-1402-26-git-send-email-wangnan0@huawei.com
---
tools/perf/util/evsel.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 77a425f..51132d3 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1363,6 +1363,22 @@ retry_open:
err);
goto try_fallback;
}
+
+ if (evsel->bpf_fd >= 0) {
+ int evt_fd = FD(evsel, cpu, thread);
+ int bpf_fd = evsel->bpf_fd;
+
+ err = ioctl(evt_fd,
+ PERF_EVENT_IOC_SET_BPF,
+ bpf_fd);
+ if (err && errno != EEXIST) {
+ pr_err("failed to attach bpf fd %d: %s\n",
+ bpf_fd, strerror(errno));
+ err = -EINVAL;
+ goto out_close;
+ }
+ }
+
set_rlimit = NO_CHANGE;
/*
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-08-28 09:20 +0200 |
| Subject | [PATCH 05/32] perf ebpf: Add the libbpf glue |
| Message-ID | <q2m7a-4Ey-57@gated-at.bofh.it> |
| In reply to | #1215170 |
The 'bpf-loader.[ch]' files are introduced in this patch. Which will be
the interface between perf and libbpf. bpf__prepare_load() resides in
bpf-loader.c. Dummy functions should be used because bpf-loader.c is
available only when CONFIG_LIBBPF is on.
Functions in bpf-loader.c should not report error explicitly. Instead,
strerror style error reporting should be used.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/n/1436445342-1402-19-git-send-email-wangnan0@huawei.com
[ split from a larger patch ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/bpf-loader.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/bpf-loader.h | 47 ++++++++++++++++++++++
2 files changed, 139 insertions(+)
create mode 100644 tools/perf/util/bpf-loader.c
create mode 100644 tools/perf/util/bpf-loader.h
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
new file mode 100644
index 0000000..88531ea
--- /dev/null
+++ b/tools/perf/util/bpf-loader.c
@@ -0,0 +1,92 @@
+/*
+ * bpf-loader.c
+ *
+ * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2015 Huawei Inc.
+ */
+
+#include <bpf/libbpf.h>
+#include "perf.h"
+#include "debug.h"
+#include "bpf-loader.h"
+
+#define DEFINE_PRINT_FN(name, level) \
+static int libbpf_##name(const char *fmt, ...) \
+{ \
+ va_list args; \
+ int ret; \
+ \
+ va_start(args, fmt); \
+ ret = veprintf(level, verbose, pr_fmt(fmt), args);\
+ va_end(args); \
+ return ret; \
+}
+
+DEFINE_PRINT_FN(warning, 0)
+DEFINE_PRINT_FN(info, 0)
+DEFINE_PRINT_FN(debug, 1)
+
+static bool libbpf_initialized;
+
+int bpf__prepare_load(const char *filename)
+{
+ struct bpf_object *obj;
+
+ if (!libbpf_initialized)
+ libbpf_set_print(libbpf_warning,
+ libbpf_info,
+ libbpf_debug);
+
+ obj = bpf_object__open(filename);
+ if (!obj) {
+ pr_debug("bpf: failed to load %s\n", filename);
+ return -EINVAL;
+ }
+
+ /*
+ * Throw object pointer away: it will be retrived using
+ * bpf_objects iterater.
+ */
+
+ return 0;
+}
+
+void bpf__clear(void)
+{
+ struct bpf_object *obj, *tmp;
+
+ bpf_object__for_each_safe(obj, tmp)
+ bpf_object__close(obj);
+}
+
+#define bpf__strerror_head(err, buf, size) \
+ char sbuf[STRERR_BUFSIZE], *emsg;\
+ if (!size)\
+ return 0;\
+ if (err < 0)\
+ err = -err;\
+ emsg = strerror_r(err, sbuf, sizeof(sbuf));\
+ switch (err) {\
+ default:\
+ scnprintf(buf, size, "%s", emsg);\
+ break;
+
+#define bpf__strerror_entry(val, fmt...)\
+ case val: {\
+ scnprintf(buf, size, fmt);\
+ break;\
+ }
+
+#define bpf__strerror_end(buf, size)\
+ }\
+ buf[size - 1] = '\0';
+
+int bpf__strerror_prepare_load(const char *filename, int err,
+ char *buf, size_t size)
+{
+ bpf__strerror_head(err, buf, size);
+ bpf__strerror_entry(EINVAL, "%s: BPF object file '%s' is invalid",
+ emsg, filename)
+ bpf__strerror_end(buf, size);
+ return 0;
+}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
new file mode 100644
index 0000000..12be630
--- /dev/null
+++ b/tools/perf/util/bpf-loader.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2015, Huawei Inc.
+ */
+#ifndef __BPF_LOADER_H
+#define __BPF_LOADER_H
+
+#include <linux/compiler.h>
+#include <string.h>
+#include "debug.h"
+
+#ifdef HAVE_LIBBPF_SUPPORT
+int bpf__prepare_load(const char *filename);
+int bpf__strerror_prepare_load(const char *filename, int err,
+ char *buf, size_t size);
+
+void bpf__clear(void);
+#else
+static inline int bpf__prepare_load(const char *filename __maybe_unused)
+{
+ pr_debug("ERROR: eBPF object loading is disabled during compiling.\n");
+ return -1;
+}
+
+static inline void bpf__clear(void) { }
+
+static inline int
+__bpf_strerror(char *buf, size_t size)
+{
+ if (!size)
+ return 0;
+ strncpy(buf,
+ "ERROR: eBPF object loading is disabled during compiling.\n",
+ size);
+ buf[size - 1] = '\0';
+ return 0;
+}
+
+static inline int
+bpf__strerror_prepare_load(const char *filename __maybe_unused,
+ int err __maybe_unused,
+ char *buf, size_t size)
+{
+ return __bpf_strerror(buf, size);
+}
+#endif
+#endif
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web