* [RFC 00/13] perf bpf: Add support to run BEGIN/END code
@ 2018-03-12 9:43 Jiri Olsa
2018-03-12 9:43 ` [PATCH 01/13] lib bpf: Add bpf_program__insns function Jiri Olsa
` (13 more replies)
0 siblings, 14 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Brendan Gregg, Stanislav Kozina, Frank Ch. Eigler, Will Cohen,
Eugene Syromiatnikov, Jerome Marchand, lkml, Ingo Molnar,
Namhyung Kim, David Ahern, Alexander Shishkin, Peter Zijlstra
hi,
this is *RFC* and the following patchset is very rough
and ugly 'prove of concept'-kind-of-toy code. I'm mostly
interested in opinions about if this could be useful in
your current eBPF usage.
Currently we can load eBPF code within the record command
and attach it to event. We have 2 ways of communicating
the data back to user: bpf-output event that goes to
perf.data or 'trace_printk' output in tracefs buffer.
AFAICS we're not covering quite large usage base that runs
code before and once the probe is finished to setup, collect
and display the collected data.
This patchset is adding support to run BEGIN and END
code snipets before and after eBPF probe is loaded.
This allow to write 'collecting' code in eBPF object,
like in the attached example (it's also part of the
patchset).
This patchset also adds 'bpf' command to ease up the
loading of eBPF files with options for compilation
and disassembly of eBPF objects:
$ perf bpf -c samples/syscall-counts.c
LLVM: dumping samples/syscall-counts.o
$ perf bpf -d samples/syscall-counts.o | head
Disassembly of raw_syscalls:sys_enter:
0: (b7) r1 = 1
b7 01 00 00 01 00 00 00
1: (7b) *(u64 *)(r10 -8) = r1
7b 1a f8 ff 00 00 00 00
2: (bf) r6 = r10
...
$ sudo perf bpf -e samples/syscall-counts.o -a
BEGIN
^CEND
comm value
firefox 182
Socket Thread 8
InotifyEventThr 26
xmonad-x86_64-l 405
...
The patchset is also available in here:
https://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/bpf
So far I need following following lines in .perfconfig to run this:
[llvm]
kbuild-dir=/home/jolsa/kernel/linux-perf
clang-opt=-I/home/jolsa/kernel/linux-perf/tools/perf/util
thoughts? ;-) thanks,
jirka
Cc: Brendan Gregg <bgregg@netflix.com>
Cc: Stanislav Kozina <skozina@redhat.com>
Cc: "Frank Ch. Eigler" <fche@redhat.com>
Cc: Will Cohen <wcohen@redhat.com>
Cc: Eugene Syromiatnikov <esyromia@redhat.com>
Cc: Jerome Marchand <jmarchan@redhat.com>
---
#include <uapi/linux/bpf.h>
#include <bpf-helpers.h>
#include <bpf-userfuncs.h>
#define TASK_COMM_LEN 16
char _license[] SEC("license") = "GPL";
int _version SEC("version") = LINUX_VERSION_CODE;
struct key_t {
char comm[TASK_COMM_LEN];
};
struct bpf_map_def SEC("maps") counts_map = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct key_t),
.value_size = sizeof(u64),
.max_entries = 100,
};
SEC("raw_syscalls:sys_enter")
int func(void *ctx)
{
u64 *val, one = 1;
struct key_t key;
char comm[TASK_COMM_LEN];
bpf_get_current_comm(&key.comm, sizeof(comm));
val = bpf_map_lookup_elem(&counts_map, &key);
if (val)
(*val)++;
else
bpf_map_update_elem(&counts_map, &key, &one, BPF_NOEXIST);
return 0;
}
int BEGIN(void)
{
print("BEGIN\n");
return 0;
}
void END(void)
{
struct key_t key = {}, next_key;
u64 value;
int i = 0;
print("END\n");
print("\n comm value\n");
while (bpfu_map_get_next_key(&counts_map, &key, &next_key) == 0) {
if (bpfu_map_lookup_elem(&counts_map, &next_key, &value))
continue;
print("%18s %16lu\n", next_key.comm, value);
key = next_key;
}
}
---
Jiri Olsa (13):
lib bpf: Add bpf_program__insns function
perf tools: Display ebpf compiling command in debug output
perf tools: Add bpf command
perf tools: Add bpf__compile function
perf bpf: Add compile option
perf bpf: Add disasm option
libbpf: Make bpf_program__next skip .text section
libbpf: Collect begin/end .text functions
libbpf: Add bpf_insn__interpret function
libbpf: Add bpf_object__run_(begin|end) functions
perf bpf: Add helper header files
perf bpf: Run begin/end programs
perf samples: Add syscall-count.c object
tools/lib/bpf/Build | 2 +-
tools/lib/bpf/interp.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tools/lib/bpf/libbpf.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++--
tools/lib/bpf/libbpf.h | 7 +++
tools/perf/Build | 7 +++
tools/perf/Makefile.config | 1 +
tools/perf/builtin-bpf.c | 319 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tools/perf/builtin.h | 1 +
tools/perf/command-list.txt | 1 +
tools/perf/perf.c | 1 +
tools/perf/samples/syscall-counts.c | 61 ++++++++++++++++++++++++
tools/perf/util/bpf-helpers.h | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/bpf-loader.c | 124 ++++++++++++++++++++++++++++++++++++++++++++-----
tools/perf/util/bpf-loader.h | 4 ++
tools/perf/util/bpf-userapi.h | 11 +++++
tools/perf/util/bpf-userfuncs.h | 19 ++++++++
tools/perf/util/llvm-utils.c | 14 ++++++
17 files changed, 1173 insertions(+), 15 deletions(-)
create mode 100644 tools/lib/bpf/interp.c
create mode 100644 tools/perf/builtin-bpf.c
create mode 100644 tools/perf/samples/syscall-counts.c
create mode 100644 tools/perf/util/bpf-helpers.h
create mode 100644 tools/perf/util/bpf-userapi.h
create mode 100644 tools/perf/util/bpf-userfuncs.h
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 01/13] lib bpf: Add bpf_program__insns function
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 9:43 ` [PATCH 02/13] perf tools: Display ebpf compiling command in debug output Jiri Olsa
` (12 subsequent siblings)
13 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Adding bpf_program__insns helper function to retrieve
prog's instructions. It's used later in the patchset.
Link: http://lkml.kernel.org/n/tip-xvpbbusx8gie33kj0et5wx6l@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/lib/bpf/libbpf.c | 7 +++++++
tools/lib/bpf/libbpf.h | 3 +++
2 files changed, 10 insertions(+)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 5bbbf285af74..6b9df10470e8 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -261,6 +261,13 @@ struct bpf_object {
};
#define obj_elf_valid(o) ((o)->efile.elf)
+struct bpf_insn*
+bpf_program__insns(struct bpf_program *prog, int *insns_cnt)
+{
+ *insns_cnt = prog->insns_cnt;
+ return prog->insns;
+}
+
static void bpf_program__unload(struct bpf_program *prog)
{
int i;
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index f85906533cdd..bfc4d0411ec5 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -180,6 +180,9 @@ int bpf_program__set_prep(struct bpf_program *prog, int nr_instance,
int bpf_program__nth_fd(struct bpf_program *prog, int n);
+struct bpf_insn*
+bpf_program__insns(struct bpf_program *prog, int *insns_cnt);
+
/*
* Adjust type of bpf program. Default is kprobe.
*/
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 02/13] perf tools: Display ebpf compiling command in debug output
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
2018-03-12 9:43 ` [PATCH 01/13] lib bpf: Add bpf_program__insns function Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 14:24 ` Arnaldo Carvalho de Melo
2018-03-20 6:29 ` [tip:perf/core] perf llvm: Display eBPF " tip-bot for Jiri Olsa
2018-03-12 9:43 ` [PATCH 03/13] perf tools: Add bpf command Jiri Olsa
` (11 subsequent siblings)
13 siblings, 2 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
In addition to template, display also the real compile
command line with all the variables substituted.
llvm compiling command template: $CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS ...
llvm compiling command : /usr/bin/clang -D__KERNEL__ -D__NR_CPUS__=24 -DLINUX_VERSION_CODE=0x41000 ...
Link: http://lkml.kernel.org/n/tip-mygjr5z3c77x9ephks7n06oc@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/util/llvm-utils.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 4952b429caa7..1cca0a2fa641 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -433,6 +433,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
char serr[STRERR_BUFSIZE];
char *kbuild_dir = NULL, *kbuild_include_opts = NULL;
const char *template = llvm_param.clang_bpf_cmd_template;
+ char *command_echo, *command_out;
if (path[0] != '-' && realpath(path, abspath) == NULL) {
err = errno;
@@ -487,6 +488,16 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
(path[0] == '-') ? path : abspath);
pr_debug("llvm compiling command template: %s\n", template);
+
+ if (asprintf(&command_echo, "echo -n \"%s\"", template) < 0)
+ goto errout;
+
+ err = read_from_pipe(command_echo, (void **) &command_out, NULL);
+ if (err)
+ goto errout;
+
+ pr_debug("llvm compiling command : %s\n", command_out);
+
err = read_from_pipe(template, &obj_buf, &obj_buf_sz);
if (err) {
pr_err("ERROR:\tunable to compile %s\n", path);
@@ -497,6 +508,8 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
goto errout;
}
+ free(command_echo);
+ free(command_out);
free(kbuild_dir);
free(kbuild_include_opts);
@@ -509,6 +522,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
*p_obj_buf_sz = obj_buf_sz;
return 0;
errout:
+ free(command_echo);
free(kbuild_dir);
free(kbuild_include_opts);
free(obj_buf);
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 03/13] perf tools: Add bpf command
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
2018-03-12 9:43 ` [PATCH 01/13] lib bpf: Add bpf_program__insns function Jiri Olsa
2018-03-12 9:43 ` [PATCH 02/13] perf tools: Display ebpf compiling command in debug output Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 9:43 ` [PATCH 04/13] perf tools: Add bpf__compile function Jiri Olsa
` (10 subsequent siblings)
13 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Adding perf bpf command to allow to provide some
fucs over ebpf objects, like compile, disassembly
and loading, which is comming in following patches.
Link: http://lkml.kernel.org/n/tip-51vi69jgn3nfa00azjlikfck@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/Build | 1 +
tools/perf/builtin-bpf.c | 199 ++++++++++++++++++++++++++++++++++++++++++++
tools/perf/builtin.h | 1 +
tools/perf/command-list.txt | 1 +
tools/perf/perf.c | 1 +
5 files changed, 203 insertions(+)
create mode 100644 tools/perf/builtin-bpf.c
diff --git a/tools/perf/Build b/tools/perf/Build
index e5232d567611..7f521ac16466 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -24,6 +24,7 @@ perf-y += builtin-mem.o
perf-y += builtin-data.o
perf-y += builtin-version.o
perf-y += builtin-c2c.o
+perf-y += builtin-bpf.o
perf-$(CONFIG_TRACE) += builtin-trace.o
perf-$(CONFIG_LIBELF) += builtin-probe.o
diff --git a/tools/perf/builtin-bpf.c b/tools/perf/builtin-bpf.c
new file mode 100644
index 000000000000..6f02352caf79
--- /dev/null
+++ b/tools/perf/builtin-bpf.c
@@ -0,0 +1,199 @@
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <time.h>
+#include <linux/compiler.h>
+#include <subcmd/parse-options.h>
+#include "builtin.h"
+#include "perf.h"
+#include "target.h"
+#include "debug.h"
+#include "parse-events.h"
+#include "evlist.h"
+#include "evsel.h"
+#include "bpf-loader.h"
+
+struct perf_bpf {
+ struct target target;
+ struct perf_evlist *evlist;
+};
+
+struct perf_bpf bpf = {
+ .target = { .uid = UINT_MAX, },
+};
+
+static volatile int done;
+static volatile int workload_exec_errno;
+
+static void sig_handler(int sig __maybe_unused)
+{
+ done = 1;
+}
+
+/*
+ * perf_evlist__prepare_workload will send a SIGUSR1
+ * if the fork fails, since we asked by setting its
+ * want_signal to true.
+ */
+static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info,
+ void *ucontext __maybe_unused)
+{
+ workload_exec_errno = info->si_value.sival_int;
+}
+
+static int create_perf_bpf_counter(struct perf_evsel *evsel)
+{
+ if (target__has_cpu(&bpf.target) && !target__has_per_thread(&bpf.target))
+ return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
+
+ return perf_evsel__open_per_thread(evsel, bpf.evlist->threads);
+}
+
+static int __cmd_bpf(int argc , const char **argv)
+{
+ struct perf_evsel *evsel;
+ bool forks = argc > 0;
+ int err, status;
+ int child_pid = -1;
+ char msg[BUFSIZ];
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 500 };
+
+ if (forks) {
+ err = perf_evlist__prepare_workload(bpf.evlist, &bpf.target,
+ argv, true,
+ workload_exec_failed_signal);
+ if (err < 0) {
+ pr_err("Couldn't run the workload!\n");
+ status = err;
+ goto out;
+ }
+
+ child_pid = bpf.evlist->workload.pid;
+ }
+
+ evlist__for_each_entry(bpf.evlist, evsel) {
+ err =create_perf_bpf_counter(evsel);
+ if (err < 0) {
+ perf_evsel__open_strerror(evsel, &bpf.target,
+ errno, msg, sizeof(msg));
+ pr_err("%s\n", msg);
+ goto out_child;
+ }
+ }
+
+ err = bpf__apply_obj_config();
+ if (err) {
+ char errbuf[BUFSIZ];
+
+ bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
+ pr_err("ERROR: Apply config to BPF failed: %s\n",
+ errbuf);
+ goto out_child;
+ }
+
+ if (forks) {
+ perf_evlist__start_workload(bpf.evlist);
+
+ if (!target__none(&bpf.target))
+ perf_evlist__enable(bpf.evlist);
+
+ waitpid(child_pid, &status, 0);
+ } else {
+ if (!target__none(&bpf.target))
+ perf_evlist__enable(bpf.evlist);
+
+ while (!done) {
+ nanosleep(&ts, NULL);
+ }
+ }
+
+ if (!target__none(&bpf.target))
+ perf_evlist__disable(bpf.evlist);
+
+ child_pid = -1;
+
+out_child:
+ if (forks) {
+ if (workload_exec_errno) {
+ const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
+ pr_err("Workload failed: %s\n", emsg);
+ return -1;
+ }
+
+ if (child_pid != -1) {
+ kill(child_pid, SIGTERM);
+ waitpid(child_pid, &status, 0);
+ }
+
+ if (WIFSIGNALED(status))
+ psignal(WTERMSIG(status), argv[0]);
+ }
+
+out:
+ perf_evlist__close(bpf.evlist);
+
+ if (err)
+ status = err;
+ return WEXITSTATUS(status);
+}
+
+int cmd_bpf(int argc, const char **argv)
+{
+ int err = -1;
+ const char * const bpf_usage[] = {
+ "perf bpf [<options>] [<command>]",
+ "perf bpf [<options>] -- <command> [<options>]",
+ NULL
+ };
+ const struct option bpf_options[] = {
+ OPT_CALLBACK('e', "event", &bpf.evlist, "event",
+ "event selector. use 'perf list' to list available events",
+ parse_events_option),
+ OPT_STRING('C', "cpu", &bpf.target.cpu_list, "cpu",
+ "list of cpus to monitor"),
+ OPT_BOOLEAN('a', "all-cpus", &bpf.target.system_wide,
+ "system-wide collection from all CPUs"),
+ OPT_STRING('p', "pid", &bpf.target.pid, "pid",
+ "record events on existing process id"),
+ OPT_STRING('t', "tid", &bpf.target.tid, "tid",
+ "record events on existing thread id"),
+ OPT_INCR('v', "verbose", &verbose,
+ "be more verbose"),
+ OPT_END()
+ };
+
+ signal(SIGINT, sig_handler);
+
+ bpf.evlist = perf_evlist__new();
+ if (bpf.evlist == NULL)
+ return -ENOMEM;
+
+ argc = parse_options(argc, argv, bpf_options, bpf_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+ if (!argc && target__none(&bpf.target))
+ usage_with_options(bpf_usage, bpf_options);
+
+ if (bpf.evlist->nr_entries == 0) {
+ pr_err("failed: No event specified\n");
+ goto out;
+ }
+
+ if (perf_evlist__create_maps(bpf.evlist, &bpf.target) < 0) {
+ if (target__has_task(&bpf.target)) {
+ pr_err("Problems finding threads of monitor\n");
+ parse_options_usage(bpf_usage, bpf_options, "p", 1);
+ parse_options_usage(NULL, bpf_options, "t", 1);
+ } else if (target__has_cpu(&bpf.target)) {
+ perror("failed to parse CPUs map");
+ parse_options_usage(bpf_usage, bpf_options, "C", 1);
+ parse_options_usage(NULL, bpf_options, "a", 1);
+ }
+ }
+
+ target__validate(&bpf.target);
+
+ err = __cmd_bpf(argc, argv);
+out:
+ perf_evlist__delete(bpf.evlist);
+ return err;
+}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 05745f3ce912..1805c65f4d01 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -39,6 +39,7 @@ int cmd_inject(int argc, const char **argv);
int cmd_mem(int argc, const char **argv);
int cmd_data(int argc, const char **argv);
int cmd_ftrace(int argc, const char **argv);
+int cmd_bpf(int argc, const char **argv);
int find_scripts(char **scripts_array, char **scripts_path_array);
#endif
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 2d0caf20ff3a..4e8e398d4f45 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -30,3 +30,4 @@ perf-test mainporcelain common
perf-timechart mainporcelain common
perf-top mainporcelain common
perf-trace mainporcelain audit
+perf-bpf mainporcelain common
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 1b3fc8ec0fa2..144cf71af0f7 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -80,6 +80,7 @@ static struct cmd_struct commands[] = {
{ "mem", cmd_mem, 0 },
{ "data", cmd_data, 0 },
{ "ftrace", cmd_ftrace, 0 },
+ { "bpf", cmd_bpf, 0 },
};
struct pager_config {
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 04/13] perf tools: Add bpf__compile function
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
` (2 preceding siblings ...)
2018-03-12 9:43 ` [PATCH 03/13] perf tools: Add bpf command Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 9:43 ` [PATCH 05/13] perf bpf: Add compile option Jiri Olsa
` (9 subsequent siblings)
13 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Adding bpf__compile function to have interface for
ebpf object compilation.
Link: http://lkml.kernel.org/n/tip-3kus9vjbiven8par9j1ju9u5@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/util/bpf-loader.c | 46 +++++++++++++++++++++++++++++++++-----------
tools/perf/util/bpf-loader.h | 2 ++
2 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index af7ad814b2c3..e59168153375 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -74,6 +74,38 @@ bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz, const char *name)
return obj;
}
+static int compile(const char *filename, void *obj_buf, size_t *obj_buf_sz)
+{
+ int err;
+
+ perf_clang__init();
+ err = perf_clang__compile_bpf(filename, obj_buf, obj_buf_sz);
+ perf_clang__cleanup();
+ if (err) {
+ pr_debug("bpf: builtin compilation failed: %d, try external compiler\n", err);
+ err = llvm__compile_bpf(filename, obj_buf, obj_buf_sz);
+ if (err)
+ return -1;
+ } else {
+ pr_debug("bpf: successfull builtin compilation\n");
+ }
+
+ return 0;
+}
+
+int bpf__compile(const char *filename)
+{
+ void *obj_buf;
+ size_t obj_buf_sz;
+
+ if (compile(filename, &obj_buf, &obj_buf_sz))
+ return -1;
+
+ /* make llvm__dump_obj to return error value */
+ llvm__dump_obj(filename, obj_buf, obj_buf_sz);
+ return 0;
+}
+
struct bpf_object *bpf__prepare_load(const char *filename, bool source)
{
struct bpf_object *obj;
@@ -86,20 +118,12 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
}
if (source) {
- int err;
void *obj_buf;
size_t obj_buf_sz;
- perf_clang__init();
- err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz);
- perf_clang__cleanup();
- if (err) {
- pr_debug("bpf: builtin compilation failed: %d, try external compiler\n", err);
- err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
- if (err)
- return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
- } else
- pr_debug("bpf: successfull builtin compilation\n");
+ if (compile(filename, &obj_buf, &obj_buf_sz))
+ return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+
obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
if (!IS_ERR(obj) && llvm_param.dump_obj)
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 5d3aefd6fae7..8c2a494cab53 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -58,6 +58,8 @@ int bpf__strerror_prepare_load(const char *filename, bool source,
struct bpf_object *bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz,
const char *name);
+int bpf__compile(const char *filename);
+
void bpf__clear(void);
int bpf__probe(struct bpf_object *obj);
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 05/13] perf bpf: Add compile option
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
` (3 preceding siblings ...)
2018-03-12 9:43 ` [PATCH 04/13] perf tools: Add bpf__compile function Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 9:43 ` [PATCH 06/13] perf bpf: Add disasm option Jiri Olsa
` (8 subsequent siblings)
13 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Adding -c/--compile option to provide compilation
for ebpf objects, like:
$ perf bpf -c samples/syscall-counts.c
LLVM: dumping samples/syscall-counts.o
Link: http://lkml.kernel.org/n/tip-w48lyepbrde7no35sxi2vtxh@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/builtin-bpf.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/tools/perf/builtin-bpf.c b/tools/perf/builtin-bpf.c
index 6f02352caf79..1ae93fd01a97 100644
--- a/tools/perf/builtin-bpf.c
+++ b/tools/perf/builtin-bpf.c
@@ -145,6 +145,7 @@ int cmd_bpf(int argc, const char **argv)
"perf bpf [<options>] -- <command> [<options>]",
NULL
};
+ const char *compile_src = NULL;
const struct option bpf_options[] = {
OPT_CALLBACK('e', "event", &bpf.evlist, "event",
"event selector. use 'perf list' to list available events",
@@ -159,6 +160,8 @@ int cmd_bpf(int argc, const char **argv)
"record events on existing thread id"),
OPT_INCR('v', "verbose", &verbose,
"be more verbose"),
+ OPT_STRING('c', "compile", &compile_src, "eBPF source",
+ "compile eBPF object"),
OPT_END()
};
@@ -170,6 +173,10 @@ int cmd_bpf(int argc, const char **argv)
argc = parse_options(argc, argv, bpf_options, bpf_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
+
+ if (compile_src)
+ return bpf__compile(compile_src);
+
if (!argc && target__none(&bpf.target))
usage_with_options(bpf_usage, bpf_options);
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 06/13] perf bpf: Add disasm option
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
` (4 preceding siblings ...)
2018-03-12 9:43 ` [PATCH 05/13] perf bpf: Add compile option Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 9:43 ` [PATCH 07/13] libbpf: Make bpf_program__next skip .text section Jiri Olsa
` (7 subsequent siblings)
13 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Add -d/--disasm option to get the sbpf assembly
code dump, like:
$ perf bpf -d ./comm1.o | head
Disassembly of raw_syscalls:sys_enter:
0: (b7) r1 = 1
b7 01 00 00 01 00 00 00
1: (7b) *(u64 *)(r10 -8) = r1
7b 1a f8 ff 00 00 00 00
2: (bf) r6 = r10
bf a6 00 00 00 00 00 00
3: (07) r6 += -24
07 06 00 00 e8 ff ff ff
4: (bf) r1 = r6
...
Link: http://lkml.kernel.org/n/tip-djopq2e6ajsg9h90hb9iuat3@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/Build | 6 +++
tools/perf/Makefile.config | 1 +
tools/perf/builtin-bpf.c | 107 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 114 insertions(+)
diff --git a/tools/perf/Build b/tools/perf/Build
index 7f521ac16466..0585fd3715d0 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -25,6 +25,7 @@ perf-y += builtin-data.o
perf-y += builtin-version.o
perf-y += builtin-c2c.o
perf-y += builtin-bpf.o
+perf-y += bpf-disasm.o
perf-$(CONFIG_TRACE) += builtin-trace.o
perf-$(CONFIG_LIBELF) += builtin-probe.o
@@ -46,6 +47,7 @@ CFLAGS_perf.o += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" \
CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))"
CFLAGS_builtin-report.o += -DTIPDIR="BUILD_STR($(tipdir_SQ))"
CFLAGS_builtin-report.o += -DDOCDIR="BUILD_STR($(srcdir_SQ)/Documentation)"
+CFLAGS_builtin-bpf.o += -I$(srctree)/kernel/bpf
libperf-y += util/
libperf-y += arch/
@@ -54,3 +56,7 @@ libperf-y += scripts/
libperf-$(CONFIG_TRACE) += trace/beauty/
gtk-y += ui/gtk/
+
+$(OUTPUT)bpf-disasm.o: ../../kernel/bpf/disasm.c FORCE
+ $(call rule_mkdir)
+ $(call if_changed_dep,cc_o_c)
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 98ff73648b51..575910cebb57 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -999,3 +999,4 @@ $(call detected_var,LIBDIR)
$(call detected_var,GTK_CFLAGS)
$(call detected_var,PERL_EMBED_CCOPTS)
$(call detected_var,PYTHON_EMBED_CCOPTS)
+$(call detected_var,srctree)
diff --git a/tools/perf/builtin-bpf.c b/tools/perf/builtin-bpf.c
index 1ae93fd01a97..7065153a9577 100644
--- a/tools/perf/builtin-bpf.c
+++ b/tools/perf/builtin-bpf.c
@@ -4,6 +4,8 @@
#include <time.h>
#include <linux/compiler.h>
#include <subcmd/parse-options.h>
+#include <bpf/bpf.h>
+#include <bpf/libbpf.h>
#include "builtin.h"
#include "perf.h"
#include "target.h"
@@ -12,6 +14,7 @@
#include "evlist.h"
#include "evsel.h"
#include "bpf-loader.h"
+#include "disasm.h"
struct perf_bpf {
struct target target;
@@ -137,6 +140,104 @@ static int __cmd_bpf(int argc , const char **argv)
return WEXITSTATUS(status);
}
+static void print_insn(struct bpf_verifier_env *env __maybe_unused, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+}
+
+static const char *print_call(void *private_data __maybe_unused,
+ const struct bpf_insn *insn __maybe_unused)
+{
+ return NULL;
+}
+
+static const char *print_imm(void *private_data __maybe_unused,
+ const struct bpf_insn *insn __maybe_unused,
+ __u64 full_imm __maybe_unused)
+{
+ return NULL;
+}
+
+static void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep)
+{
+ unsigned char *data = arg;
+ unsigned int i;
+
+ for (i = 0; i < n; i++) {
+ const char *pfx = "";
+
+ if (!i)
+ /* nothing */;
+ else if (!(i % 16))
+ fprintf(f, "\n");
+ else if (!(i % 8))
+ fprintf(f, " ");
+ else
+ pfx = sep;
+
+ fprintf(f, "%s%02hhx", i ? pfx : "", data[i]);
+ }
+}
+
+static int disasm_fprintf(FILE *out, const char *filename, bool opcodes)
+{
+ const struct bpf_insn_cbs cbs = {
+ .cb_print = print_insn,
+ .cb_call = print_call,
+ .cb_imm = print_imm,
+ .private_data = NULL,
+ };
+ bool double_insn = false;
+ struct bpf_program *prog;
+ struct bpf_object *obj;
+ int i;
+
+ obj = bpf__prepare_load(filename, false);
+ if (IS_ERR(obj))
+ return -1;
+
+ bpf_object__for_each_program(prog, obj) {
+ struct bpf_insn *insn;
+ int insns_cnt;
+
+ fprintf(out, "Disassembly of %s:\n", bpf_program__title(prog, false));
+
+ insn = bpf_program__insns(prog, &insns_cnt);
+ if (!insn) {
+ pr_err("failed: NULL instructions\n");
+ return -1;
+ }
+
+ for (i = 0; i < (int) insns_cnt; i++) {
+ if (double_insn) {
+ double_insn = false;
+ continue;
+ }
+
+ double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
+
+ printf("% 4d: ", i);
+ print_bpf_insn(&cbs, NULL, insn + i, true);
+
+ if (opcodes) {
+ printf(" ");
+ fprint_hex(stdout, insn + i, 8, " ");
+ if (double_insn && i < (int) (insns_cnt*sizeof(*insn)) - 1) {
+ printf(" ");
+ fprint_hex(stdout, insn + i + 1, 8, " ");
+ }
+ printf("\n");
+ }
+ }
+ }
+
+ return 0;
+}
+
int cmd_bpf(int argc, const char **argv)
{
int err = -1;
@@ -146,6 +247,7 @@ int cmd_bpf(int argc, const char **argv)
NULL
};
const char *compile_src = NULL;
+ const char *disasm_obj = NULL;
const struct option bpf_options[] = {
OPT_CALLBACK('e', "event", &bpf.evlist, "event",
"event selector. use 'perf list' to list available events",
@@ -162,6 +264,8 @@ int cmd_bpf(int argc, const char **argv)
"be more verbose"),
OPT_STRING('c', "compile", &compile_src, "eBPF source",
"compile eBPF object"),
+ OPT_STRING('d', "disasm", &disasm_obj, "eBPF object",
+ "disasm eBPF object"),
OPT_END()
};
@@ -177,6 +281,9 @@ int cmd_bpf(int argc, const char **argv)
if (compile_src)
return bpf__compile(compile_src);
+ if (disasm_obj)
+ return disasm_fprintf(stdout, disasm_obj, true);
+
if (!argc && target__none(&bpf.target))
usage_with_options(bpf_usage, bpf_options);
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 07/13] libbpf: Make bpf_program__next skip .text section
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
` (5 preceding siblings ...)
2018-03-12 9:43 ` [PATCH 06/13] perf bpf: Add disasm option Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 9:43 ` [PATCH 08/13] libbpf: Collect begin/end .text functions Jiri Olsa
` (6 subsequent siblings)
13 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Skip .text section in bpf_program__next, so it iterates
only throught the probes code. We are about to add .text
code support, so the .text section needs to get separated
from probes.
Link: http://lkml.kernel.org/n/tip-lcftc9k0fby5b5g2o0lhum8x@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/lib/bpf/libbpf.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 6b9df10470e8..07a6d8f5e5ab 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1705,22 +1705,34 @@ void *bpf_object__priv(struct bpf_object *obj)
struct bpf_program *
bpf_program__next(struct bpf_program *prev, struct bpf_object *obj)
{
+ struct bpf_program *prog;
size_t idx;
if (!obj->programs)
return NULL;
+
/* First handler */
if (prev == NULL)
- return &obj->programs[0];
+ idx = 0;
+ else
+ idx = (prev - obj->programs) + 1;
- if (prev->obj != obj) {
+ if (prev && (prev->obj != obj)) {
pr_warning("error: program handler doesn't match object\n");
return NULL;
}
- idx = (prev - obj->programs) + 1;
if (idx >= obj->nr_programs)
return NULL;
+
+ prog = &obj->programs[idx];
+
+ if (prog->idx == obj->efile.text_shndx)
+ idx++;
+
+ if (idx >= obj->nr_programs)
+ return NULL;
+
return &obj->programs[idx];
}
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 08/13] libbpf: Collect begin/end .text functions
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
` (6 preceding siblings ...)
2018-03-12 9:43 ` [PATCH 07/13] libbpf: Make bpf_program__next skip .text section Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 9:43 ` [PATCH 09/13] libbpf: Add bpf_insn__interpret function Jiri Olsa
` (5 subsequent siblings)
13 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Collect begin/end functions from .text section,
so they could be executed before/after probes.
Link: http://lkml.kernel.org/n/tip-hj1hwb7fshdwco706j22ela3@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/lib/bpf/libbpf.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 07a6d8f5e5ab..26231e278bb8 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -225,6 +225,10 @@ struct bpf_object {
struct bpf_map *maps;
size_t nr_maps;
+ struct bpf_program *text;
+ struct bpf_insn *insn_begin;
+ struct bpf_insn *insn_end;
+
bool loaded;
/*
@@ -440,6 +444,68 @@ bpf_object__init_prog_names(struct bpf_object *obj)
return 0;
}
+static int
+bpf_object__init_text(struct bpf_object *obj)
+{
+ Elf_Data *symbols = obj->efile.symbols;
+ struct bpf_program *prog;
+ size_t pi, si;
+
+ if (obj->efile.text_shndx == -1)
+ return 0;
+
+ for (pi = 0; pi < obj->nr_programs; pi++) {
+ prog = &obj->programs[pi];
+ if (prog->idx != obj->efile.text_shndx)
+ continue;
+
+ obj->text = prog;
+
+ for (si = 0; si < symbols->d_size / sizeof(GElf_Sym); si++) {
+ bool is_end = false, is_begin = false;
+ struct bpf_insn *insn;
+ const char *name = NULL;
+ unsigned int insn_idx;
+ GElf_Sym sym;
+
+ if (!gelf_getsym(symbols, si, &sym))
+ continue;
+ if (sym.st_shndx != prog->idx)
+ continue;
+ if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL)
+ continue;
+
+ name = elf_strptr(obj->efile.elf,
+ obj->efile.strtabidx,
+ sym.st_name);
+ if (!name) {
+ pr_warning("failed to get sym name string for prog %s\n",
+ prog->section_name);
+ return -LIBBPF_ERRNO__LIBELF;
+ }
+
+ is_begin = !strcmp(name, "BEGIN");
+ is_end = !strcmp(name, "END");
+
+ if (!is_begin && !is_end)
+ continue;
+
+ insn_idx = sym.st_value / sizeof(struct bpf_insn);
+ insn = &prog->insns[insn_idx];
+
+ pr_debug("set %s to %p\n", name, insn);
+
+ if (is_begin)
+ obj->insn_begin = insn;
+ else
+ obj->insn_end = insn;
+ }
+ }
+
+ return 0;
+}
+
+
static struct bpf_object *bpf_object__new(const char *path,
void *obj_buf,
size_t obj_buf_sz)
@@ -464,6 +530,7 @@ static struct bpf_object *bpf_object__new(const char *path,
obj->efile.obj_buf = obj_buf;
obj->efile.obj_buf_sz = obj_buf_sz;
obj->efile.maps_shndx = -1;
+ obj->efile.text_shndx = -1;
obj->loaded = false;
@@ -890,6 +957,9 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
goto out;
}
err = bpf_object__init_prog_names(obj);
+ if (err)
+ goto out;
+ err = bpf_object__init_text(obj);
out:
return err;
}
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 09/13] libbpf: Add bpf_insn__interpret function
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
` (7 preceding siblings ...)
2018-03-12 9:43 ` [PATCH 08/13] libbpf: Collect begin/end .text functions Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 15:44 ` Arnaldo Carvalho de Melo
2018-03-12 9:43 ` [PATCH 10/13] libbpf: Add bpf_object__run_(begin|end) functions Jiri Olsa
` (4 subsequent siblings)
13 siblings, 1 reply; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Adding bpf_insn__interpret function to run ebpf program
in user space.
It's 'borrowed' from systemtap code, I still need to figure
the proper credits, that will go to the file header in case
this would ever go in.
Link: http://lkml.kernel.org/n/tip-qqxsyw6imdisj3dydd6e21y7@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/lib/bpf/Build | 2 +-
tools/lib/bpf/interp.c | 245 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 246 insertions(+), 1 deletion(-)
create mode 100644 tools/lib/bpf/interp.c
diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build
index 64c679d67109..af99109f3d2d 100644
--- a/tools/lib/bpf/Build
+++ b/tools/lib/bpf/Build
@@ -1 +1 @@
-libbpf-y := libbpf.o bpf.o nlattr.o
+libbpf-y := libbpf.o bpf.o nlattr.o interp.o
diff --git a/tools/lib/bpf/interp.c b/tools/lib/bpf/interp.c
new file mode 100644
index 000000000000..2ceb6a0836c3
--- /dev/null
+++ b/tools/lib/bpf/interp.c
@@ -0,0 +1,245 @@
+#include <uapi/linux/bpf.h>
+#include <stdlib.h>
+#include "interp.h"
+
+u64 bpf_interp__run(struct bpf_interp *interp)
+{
+ const struct bpf_insn *i = interp->insns + interp->insns_start;
+ u64 stack[512 / 8];
+ u64 regs[MAX_BPF_REG];
+
+ regs[BPF_REG_10] = (uintptr_t)stack + sizeof(stack);
+
+ while ((size_t)(i - interp->insns) < interp->insns_cnt) {
+ u64 dr, sr, si, s1;
+
+ dr = regs[i->dst_reg];
+ sr = regs[i->src_reg];
+ si = i->imm;
+ s1 = i->code & BPF_X ? sr : si;
+
+ switch (i->code) {
+ case BPF_LDX | BPF_MEM | BPF_B:
+ dr = *(u8 *)((uintptr_t) sr + i->off);
+ break;
+ case BPF_LDX | BPF_MEM | BPF_H:
+ dr = *(u16 *)((uintptr_t) sr + i->off);
+ break;
+ case BPF_LDX | BPF_MEM | BPF_W:
+ dr = *(u32 *)((uintptr_t) sr + i->off);
+ break;
+ case BPF_LDX | BPF_MEM | BPF_DW:
+ dr = *(u64 *)((uintptr_t) sr + i->off);
+ break;
+ case BPF_ST | BPF_MEM | BPF_B:
+ sr = si;
+ /* Fallthrough */
+ case BPF_STX | BPF_MEM | BPF_B:
+ *(u8 *)((uintptr_t) dr + i->off) = sr;
+ goto nowrite;
+ case BPF_ST | BPF_MEM | BPF_H:
+ sr = si;
+ /* Fallthrough */
+ case BPF_STX | BPF_MEM | BPF_H:
+ *(u16 *)((uintptr_t) dr + i->off) = sr;
+ goto nowrite;
+ case BPF_ST | BPF_MEM | BPF_W:
+ sr = si;
+ /* Fallthrough */
+ case BPF_STX | BPF_MEM | BPF_W:
+ *(u32 *)((uintptr_t) dr + i->off) = sr;
+ goto nowrite;
+ case BPF_ST | BPF_MEM | BPF_DW:
+ sr = si;
+ /* Fallthrough */
+ case BPF_STX | BPF_MEM | BPF_DW:
+ *(u64 *)((uintptr_t) dr + i->off) = sr;
+ goto nowrite;
+
+ case BPF_ALU64 | BPF_ADD | BPF_X:
+ case BPF_ALU64 | BPF_ADD | BPF_K:
+ dr += s1;
+ break;
+ case BPF_ALU64 | BPF_SUB | BPF_X:
+ case BPF_ALU64 | BPF_SUB | BPF_K:
+ dr -= s1;
+ break;
+ case BPF_ALU64 | BPF_AND | BPF_X:
+ case BPF_ALU64 | BPF_AND | BPF_K:
+ dr &= s1;
+ break;
+ case BPF_ALU64 | BPF_OR | BPF_X:
+ case BPF_ALU64 | BPF_OR | BPF_K:
+ dr |= s1;
+ break;
+ case BPF_ALU64 | BPF_LSH | BPF_X:
+ case BPF_ALU64 | BPF_LSH | BPF_K:
+ dr <<= s1;
+ break;
+ case BPF_ALU64 | BPF_RSH | BPF_X:
+ case BPF_ALU64 | BPF_RSH | BPF_K:
+ dr >>= s1;
+ break;
+ case BPF_ALU64 | BPF_XOR | BPF_X:
+ case BPF_ALU64 | BPF_XOR | BPF_K:
+ dr ^= s1;
+ break;
+ case BPF_ALU64 | BPF_MUL | BPF_X:
+ case BPF_ALU64 | BPF_MUL | BPF_K:
+ dr *= s1;
+ break;
+ case BPF_ALU64 | BPF_MOV | BPF_X:
+ case BPF_ALU64 | BPF_MOV | BPF_K:
+ dr = s1;
+ break;
+ case BPF_ALU64 | BPF_ARSH | BPF_X:
+ case BPF_ALU64 | BPF_ARSH | BPF_K:
+ dr = (u64) dr >> s1;
+ break;
+ case BPF_ALU64 | BPF_NEG:
+ dr = -sr;
+ /* Fallthrough */
+ case BPF_ALU64 | BPF_DIV | BPF_X:
+ case BPF_ALU64 | BPF_DIV | BPF_K:
+ if (s1 == 0)
+ return 0;
+ dr /= s1;
+ break;
+ case BPF_ALU64 | BPF_MOD | BPF_X:
+ case BPF_ALU64 | BPF_MOD | BPF_K:
+ if (s1 == 0)
+ return 0;
+ dr %= s1;
+ break;
+
+ case BPF_ALU | BPF_ADD | BPF_X:
+ case BPF_ALU | BPF_ADD | BPF_K:
+ dr = (u32)(dr + s1);
+ break;
+ case BPF_ALU | BPF_SUB | BPF_X:
+ case BPF_ALU | BPF_SUB | BPF_K:
+ dr = (u32)(dr - s1);
+ break;
+ case BPF_ALU | BPF_AND | BPF_X:
+ case BPF_ALU | BPF_AND | BPF_K:
+ dr = (u32)(dr & s1);
+ break;
+ case BPF_ALU | BPF_OR | BPF_X:
+ case BPF_ALU | BPF_OR | BPF_K:
+ dr = (u32)(dr | s1);
+ break;
+ case BPF_ALU | BPF_LSH | BPF_X:
+ case BPF_ALU | BPF_LSH | BPF_K:
+ dr = (u32)dr << s1;
+ break;
+ case BPF_ALU | BPF_RSH | BPF_X:
+ case BPF_ALU | BPF_RSH | BPF_K:
+ dr = (u32)dr >> s1;
+ break;
+ case BPF_ALU | BPF_XOR | BPF_X:
+ case BPF_ALU | BPF_XOR | BPF_K:
+ dr = (u32)(dr ^ s1);
+ break;
+ case BPF_ALU | BPF_MUL | BPF_X:
+ case BPF_ALU | BPF_MUL | BPF_K:
+ dr = (u32)(dr * s1);
+ break;
+ case BPF_ALU | BPF_MOV | BPF_X:
+ case BPF_ALU | BPF_MOV | BPF_K:
+ dr = (u32)s1;
+ break;
+ case BPF_ALU | BPF_ARSH | BPF_X:
+ case BPF_ALU | BPF_ARSH | BPF_K:
+ dr = (u32)dr >> s1;
+ break;
+ case BPF_ALU | BPF_NEG:
+ dr = -(u32)sr;
+ /* Fallthrough */
+ case BPF_ALU | BPF_DIV | BPF_X:
+ case BPF_ALU | BPF_DIV | BPF_K:
+ if ((u32)s1 == 0)
+ return 0;
+ dr = (u32)dr / (u32)s1;
+ break;
+ case BPF_ALU | BPF_MOD | BPF_X:
+ case BPF_ALU | BPF_MOD | BPF_K:
+ if ((u32)s1 == 0)
+ return 0;
+ dr = (u32)dr % (u32)s1;
+ break;
+
+ case BPF_LD | BPF_IMM | BPF_DW:
+ switch (i->src_reg) {
+ case 0:
+ dr = (u32)si | ((u64 )i[1].imm << 32);
+ break;
+ case BPF_PSEUDO_MAP_FD:
+ dr = (u64) si;
+ break;
+ default:
+ abort();
+ }
+ regs[i->dst_reg] = dr;
+ i += 2;
+ continue;
+
+ case BPF_JMP | BPF_JEQ | BPF_X:
+ case BPF_JMP | BPF_JEQ | BPF_K:
+ if (dr == s1)
+ goto dojmp;
+ goto nowrite;
+ case BPF_JMP | BPF_JNE | BPF_X:
+ case BPF_JMP | BPF_JNE | BPF_K:
+ if (dr != s1)
+ goto dojmp;
+ goto nowrite;
+ case BPF_JMP | BPF_JGT | BPF_X:
+ case BPF_JMP | BPF_JGT | BPF_K:
+ if (dr > s1)
+ goto dojmp;
+ goto nowrite;
+ case BPF_JMP | BPF_JGE | BPF_X:
+ case BPF_JMP | BPF_JGE | BPF_K:
+ if (dr >= s1)
+ goto dojmp;
+ goto nowrite;
+ case BPF_JMP | BPF_JSGT | BPF_X:
+ case BPF_JMP | BPF_JSGT | BPF_K:
+ if ((u64) dr > (u64) s1)
+ goto dojmp;
+ goto nowrite;
+ case BPF_JMP | BPF_JSGE | BPF_X:
+ case BPF_JMP | BPF_JSGE | BPF_K:
+ if ((u64) dr >= (u64) s1)
+ goto dojmp;
+ goto nowrite;
+ case BPF_JMP | BPF_JSET | BPF_X:
+ case BPF_JMP | BPF_JSET | BPF_K:
+ if (dr & s1)
+ goto dojmp;
+ goto nowrite;
+ case BPF_JMP | BPF_JA:
+ dojmp:
+ i += 1 + i->off;
+ continue;
+
+ case BPF_JMP | BPF_CALL:
+ if (interp->call_cb(interp, si, regs))
+ return (u64) -1;
+
+ goto nowrite;
+
+ case BPF_JMP | BPF_EXIT:
+ return regs[0];
+
+ default:
+ abort();
+ }
+
+ regs[i->dst_reg] = dr;
+ nowrite:
+ i++;
+ }
+
+ return 0;
+}
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 10/13] libbpf: Add bpf_object__run_(begin|end) functions
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
` (8 preceding siblings ...)
2018-03-12 9:43 ` [PATCH 09/13] libbpf: Add bpf_insn__interpret function Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 9:43 ` [PATCH 11/13] perf bpf: Add helper header files Jiri Olsa
` (3 subsequent siblings)
13 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Add bpf_object__run_(begin|end) functions to run
BEGIN/END code for specific object.
Link: http://lkml.kernel.org/n/tip-hj1hwb7fshdwco706j22ela3@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/lib/bpf/libbpf.c | 30 ++++++++++++++++++++++++++++++
tools/lib/bpf/libbpf.h | 4 ++++
2 files changed, 34 insertions(+)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 26231e278bb8..f1f999d64d6a 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -45,6 +45,7 @@
#include "libbpf.h"
#include "bpf.h"
+#include "interp.h"
#ifndef EM_BPF
#define EM_BPF 247
@@ -2107,3 +2108,32 @@ int bpf_prog_load(const char *file, enum bpf_prog_type type,
*prog_fd = bpf_program__fd(first_prog);
return 0;
}
+
+static u64 bpf_program__run(struct bpf_program *prog,
+ struct bpf_insn *insn,
+ struct bpf_interp *interp)
+{
+ interp->insns = prog->insns;
+ interp->insns_cnt = prog->insns_cnt;
+ interp->insns_start = insn - prog->insns;
+
+ return bpf_interp__run(interp);
+}
+
+u64 bpf_object__run_begin(struct bpf_object *obj, struct bpf_interp *interp)
+{
+ struct bpf_program *prog = obj->text;
+ struct bpf_insn *insn = obj->insn_begin;
+
+ pr_debug("running BEGIN(%p) for %s\n", insn, prog->name);
+ return insn && bpf_program__run(obj->text, insn, interp);
+}
+
+u64 bpf_object__run_end(struct bpf_object *obj, struct bpf_interp *interp)
+{
+ struct bpf_program *prog = obj->text;
+ struct bpf_insn *insn = obj->insn_end;
+
+ pr_debug("running END(%p) for %s\n", insn, prog->name);
+ return insn && bpf_program__run(obj->text, insn, interp);
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index bfc4d0411ec5..8ac4d4efcc1b 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -96,6 +96,10 @@ struct bpf_program;
struct bpf_program *bpf_program__next(struct bpf_program *prog,
struct bpf_object *obj);
+struct bpf_interp;
+u64 bpf_object__run_begin(struct bpf_object *obj, struct bpf_interp *interp);
+u64 bpf_object__run_end(struct bpf_object *obj, struct bpf_interp *interp);
+
#define bpf_object__for_each_program(pos, obj) \
for ((pos) = bpf_program__next(NULL, (obj)); \
(pos) != NULL; \
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 11/13] perf bpf: Add helper header files
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
` (9 preceding siblings ...)
2018-03-12 9:43 ` [PATCH 10/13] libbpf: Add bpf_object__run_(begin|end) functions Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 18:44 ` Alexei Starovoitov
2018-03-13 1:35 ` Arnaldo Carvalho de Melo
2018-03-12 9:43 ` [PATCH 12/13] perf bpf: Run begin/end programs Jiri Olsa
` (2 subsequent siblings)
13 siblings, 2 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Adding following header files with defines for kernel
and user space ebpf calls:
bpf-helpers.h
bpf-userfuncs.h
bpf-userapi.h
Link: http://lkml.kernel.org/n/tip-sku9te4ouxg6svjtloh2nwdq@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/util/bpf-helpers.h | 246 ++++++++++++++++++++++++++++++++++++++++
tools/perf/util/bpf-userapi.h | 11 ++
tools/perf/util/bpf-userfuncs.h | 19 ++++
3 files changed, 276 insertions(+)
create mode 100644 tools/perf/util/bpf-helpers.h
create mode 100644 tools/perf/util/bpf-userapi.h
create mode 100644 tools/perf/util/bpf-userfuncs.h
diff --git a/tools/perf/util/bpf-helpers.h b/tools/perf/util/bpf-helpers.h
new file mode 100644
index 000000000000..5ec52420e906
--- /dev/null
+++ b/tools/perf/util/bpf-helpers.h
@@ -0,0 +1,246 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __BPF_HELPERS_H
+#define __BPF_HELPERS_H
+
+#include "bpf-userfuncs.h"
+
+/*
+ * helper macro to place programs, maps, license in
+ * different sections in elf_bpf file. Section names
+ * are interpreted by elf_bpf loader
+ */
+#define SEC(NAME) __attribute__((section(NAME), used))
+
+/* helper functions called from eBPF programs written in C */
+static void *(*bpf_map_lookup_elem)(void *map, void *key) =
+ (void *) BPF_FUNC_map_lookup_elem;
+static int (*bpf_map_update_elem)(void *map, void *key, void *value,
+ unsigned long long flags) =
+ (void *) BPF_FUNC_map_update_elem;
+static int (*bpf_map_delete_elem)(void *map, void *key) =
+ (void *) BPF_FUNC_map_delete_elem;
+static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr) =
+ (void *) BPF_FUNC_probe_read;
+static unsigned long long (*bpf_ktime_get_ns)(void) =
+ (void *) BPF_FUNC_ktime_get_ns;
+static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
+ (void *) BPF_FUNC_trace_printk;
+static void (*bpf_tail_call)(void *ctx, void *map, int index) =
+ (void *) BPF_FUNC_tail_call;
+static unsigned long long (*bpf_get_smp_processor_id)(void) =
+ (void *) BPF_FUNC_get_smp_processor_id;
+static unsigned long long (*bpf_get_current_pid_tgid)(void) =
+ (void *) BPF_FUNC_get_current_pid_tgid;
+static unsigned long long (*bpf_get_current_uid_gid)(void) =
+ (void *) BPF_FUNC_get_current_uid_gid;
+static int (*bpf_get_current_comm)(void *buf, int buf_size) =
+ (void *) BPF_FUNC_get_current_comm;
+static unsigned long long (*bpf_perf_event_read)(void *map,
+ unsigned long long flags) =
+ (void *) BPF_FUNC_perf_event_read;
+static int (*bpf_clone_redirect)(void *ctx, int ifindex, int flags) =
+ (void *) BPF_FUNC_clone_redirect;
+static int (*bpf_redirect)(int ifindex, int flags) =
+ (void *) BPF_FUNC_redirect;
+static int (*bpf_redirect_map)(void *map, int key, int flags) =
+ (void *) BPF_FUNC_redirect_map;
+static int (*bpf_perf_event_output)(void *ctx, void *map,
+ unsigned long long flags, void *data,
+ int size) =
+ (void *) BPF_FUNC_perf_event_output;
+static int (*bpf_get_stackid)(void *ctx, void *map, int flags) =
+ (void *) BPF_FUNC_get_stackid;
+static int (*bpf_probe_write_user)(void *dst, void *src, int size) =
+ (void *) BPF_FUNC_probe_write_user;
+static int (*bpf_current_task_under_cgroup)(void *map, int index) =
+ (void *) BPF_FUNC_current_task_under_cgroup;
+static int (*bpf_skb_get_tunnel_key)(void *ctx, void *key, int size, int flags) =
+ (void *) BPF_FUNC_skb_get_tunnel_key;
+static int (*bpf_skb_set_tunnel_key)(void *ctx, void *key, int size, int flags) =
+ (void *) BPF_FUNC_skb_set_tunnel_key;
+static int (*bpf_skb_get_tunnel_opt)(void *ctx, void *md, int size) =
+ (void *) BPF_FUNC_skb_get_tunnel_opt;
+static int (*bpf_skb_set_tunnel_opt)(void *ctx, void *md, int size) =
+ (void *) BPF_FUNC_skb_set_tunnel_opt;
+static unsigned long long (*bpf_get_prandom_u32)(void) =
+ (void *) BPF_FUNC_get_prandom_u32;
+static int (*bpf_xdp_adjust_head)(void *ctx, int offset) =
+ (void *) BPF_FUNC_xdp_adjust_head;
+static int (*bpf_xdp_adjust_meta)(void *ctx, int offset) =
+ (void *) BPF_FUNC_xdp_adjust_meta;
+static int (*bpf_setsockopt)(void *ctx, int level, int optname, void *optval,
+ int optlen) =
+ (void *) BPF_FUNC_setsockopt;
+static int (*bpf_getsockopt)(void *ctx, int level, int optname, void *optval,
+ int optlen) =
+ (void *) BPF_FUNC_getsockopt;
+static int (*bpf_sock_ops_cb_flags_set)(void *ctx, int flags) =
+ (void *) BPF_FUNC_sock_ops_cb_flags_set;
+static int (*bpf_sk_redirect_map)(void *ctx, void *map, int key, int flags) =
+ (void *) BPF_FUNC_sk_redirect_map;
+static int (*bpf_sock_map_update)(void *map, void *key, void *value,
+ unsigned long long flags) =
+ (void *) BPF_FUNC_sock_map_update;
+static int (*bpf_perf_event_read_value)(void *map, unsigned long long flags,
+ void *buf, unsigned int buf_size) =
+ (void *) BPF_FUNC_perf_event_read_value;
+static int (*bpf_perf_prog_read_value)(void *ctx, void *buf,
+ unsigned int buf_size) =
+ (void *) BPF_FUNC_perf_prog_read_value;
+static int (*bpf_override_return)(void *ctx, unsigned long rc) =
+ (void *) BPF_FUNC_override_return;
+
+/*
+ * llvm builtin functions that eBPF C program may use to
+ * emit BPF_LD_ABS and BPF_LD_IND instructions
+ */
+struct sk_buff;
+unsigned long long load_byte(void *skb,
+ unsigned long long off) asm("llvm.bpf.load.byte");
+unsigned long long load_half(void *skb,
+ unsigned long long off) asm("llvm.bpf.load.half");
+unsigned long long load_word(void *skb,
+ unsigned long long off) asm("llvm.bpf.load.word");
+
+/*
+ * a helper structure used by eBPF C program
+ * to describe map attributes to elf_bpf loader
+ */
+struct bpf_map_def {
+ unsigned int type;
+ unsigned int key_size;
+ unsigned int value_size;
+ unsigned int max_entries;
+ unsigned int map_flags;
+ unsigned int inner_map_idx;
+ unsigned int numa_node;
+};
+
+static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) =
+ (void *) BPF_FUNC_skb_load_bytes;
+static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) =
+ (void *) BPF_FUNC_skb_store_bytes;
+static int (*bpf_l3_csum_replace)(void *ctx, int off, int from, int to, int flags) =
+ (void *) BPF_FUNC_l3_csum_replace;
+static int (*bpf_l4_csum_replace)(void *ctx, int off, int from, int to, int flags) =
+ (void *) BPF_FUNC_l4_csum_replace;
+static int (*bpf_skb_under_cgroup)(void *ctx, void *map, int index) =
+ (void *) BPF_FUNC_skb_under_cgroup;
+static int (*bpf_skb_change_head)(void *, int len, int flags) =
+ (void *) BPF_FUNC_skb_change_head;
+
+/* Fall back to what the compiler says */
+#ifndef bpf_target_defined
+#if defined(__x86_64__)
+ #define bpf_target_x86
+#elif defined(__s390x__)
+ #define bpf_target_s930x
+#elif defined(__aarch64__)
+ #define bpf_target_arm64
+#elif defined(__mips__)
+ #define bpf_target_mips
+#elif defined(__powerpc__)
+ #define bpf_target_powerpc
+#elif defined(__sparc__)
+ #define bpf_target_sparc
+#endif
+#endif
+
+#if defined(bpf_target_x86)
+
+#define PT_REGS_PARM1(x) ((x)->di)
+#define PT_REGS_PARM2(x) ((x)->si)
+#define PT_REGS_PARM3(x) ((x)->dx)
+#define PT_REGS_PARM4(x) ((x)->cx)
+#define PT_REGS_PARM5(x) ((x)->r8)
+#define PT_REGS_RET(x) ((x)->sp)
+#define PT_REGS_FP(x) ((x)->bp)
+#define PT_REGS_RC(x) ((x)->ax)
+#define PT_REGS_SP(x) ((x)->sp)
+#define PT_REGS_IP(x) ((x)->ip)
+
+#elif defined(bpf_target_s390x)
+
+#define PT_REGS_PARM1(x) ((x)->gprs[2])
+#define PT_REGS_PARM2(x) ((x)->gprs[3])
+#define PT_REGS_PARM3(x) ((x)->gprs[4])
+#define PT_REGS_PARM4(x) ((x)->gprs[5])
+#define PT_REGS_PARM5(x) ((x)->gprs[6])
+#define PT_REGS_RET(x) ((x)->gprs[14])
+#define PT_REGS_FP(x) ((x)->gprs[11]) /* Works only with CONFIG_FRAME_POINTER */
+#define PT_REGS_RC(x) ((x)->gprs[2])
+#define PT_REGS_SP(x) ((x)->gprs[15])
+#define PT_REGS_IP(x) ((x)->psw.addr)
+
+#elif defined(bpf_target_arm64)
+
+#define PT_REGS_PARM1(x) ((x)->regs[0])
+#define PT_REGS_PARM2(x) ((x)->regs[1])
+#define PT_REGS_PARM3(x) ((x)->regs[2])
+#define PT_REGS_PARM4(x) ((x)->regs[3])
+#define PT_REGS_PARM5(x) ((x)->regs[4])
+#define PT_REGS_RET(x) ((x)->regs[30])
+#define PT_REGS_FP(x) ((x)->regs[29]) /* Works only with CONFIG_FRAME_POINTER */
+#define PT_REGS_RC(x) ((x)->regs[0])
+#define PT_REGS_SP(x) ((x)->sp)
+#define PT_REGS_IP(x) ((x)->pc)
+
+#elif defined(bpf_target_mips)
+
+#define PT_REGS_PARM1(x) ((x)->regs[4])
+#define PT_REGS_PARM2(x) ((x)->regs[5])
+#define PT_REGS_PARM3(x) ((x)->regs[6])
+#define PT_REGS_PARM4(x) ((x)->regs[7])
+#define PT_REGS_PARM5(x) ((x)->regs[8])
+#define PT_REGS_RET(x) ((x)->regs[31])
+#define PT_REGS_FP(x) ((x)->regs[30]) /* Works only with CONFIG_FRAME_POINTER */
+#define PT_REGS_RC(x) ((x)->regs[1])
+#define PT_REGS_SP(x) ((x)->regs[29])
+#define PT_REGS_IP(x) ((x)->cp0_epc)
+
+#elif defined(bpf_target_powerpc)
+
+#define PT_REGS_PARM1(x) ((x)->gpr[3])
+#define PT_REGS_PARM2(x) ((x)->gpr[4])
+#define PT_REGS_PARM3(x) ((x)->gpr[5])
+#define PT_REGS_PARM4(x) ((x)->gpr[6])
+#define PT_REGS_PARM5(x) ((x)->gpr[7])
+#define PT_REGS_RC(x) ((x)->gpr[3])
+#define PT_REGS_SP(x) ((x)->sp)
+#define PT_REGS_IP(x) ((x)->nip)
+
+#elif defined(bpf_target_sparc)
+
+#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0])
+#define PT_REGS_PARM2(x) ((x)->u_regs[UREG_I1])
+#define PT_REGS_PARM3(x) ((x)->u_regs[UREG_I2])
+#define PT_REGS_PARM4(x) ((x)->u_regs[UREG_I3])
+#define PT_REGS_PARM5(x) ((x)->u_regs[UREG_I4])
+#define PT_REGS_RET(x) ((x)->u_regs[UREG_I7])
+#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0])
+#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP])
+
+/* Should this also be a bpf_target check for the sparc case? */
+#if defined(__arch64__)
+#define PT_REGS_IP(x) ((x)->tpc)
+#else
+#define PT_REGS_IP(x) ((x)->pc)
+#endif
+
+#endif
+
+#ifdef bpf_target_powerpc
+#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; })
+#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
+#elif bpf_target_sparc
+#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); })
+#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
+#else
+#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ \
+ bpf_probe_read(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); })
+#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) ({ \
+ bpf_probe_read(&(ip), sizeof(ip), \
+ (void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
+#endif
+
+#endif
diff --git a/tools/perf/util/bpf-userapi.h b/tools/perf/util/bpf-userapi.h
new file mode 100644
index 000000000000..63f2b4c13a5c
--- /dev/null
+++ b/tools/perf/util/bpf-userapi.h
@@ -0,0 +1,11 @@
+#ifndef __BPF_USERAPI_H
+#define __BPF_USERAPI_H
+
+enum {
+ BPF_FUNC_USER_START = 10000,
+ BPF_FUNC_USER_print = BPF_FUNC_USER_START,
+ BPF_FUNC_USER_bpf_map_get_next_key,
+ BPF_FUNC_USER_bpf_map_lookup_elem,
+};
+
+#endif /* __BPF_USERFUNCS_H */
diff --git a/tools/perf/util/bpf-userfuncs.h b/tools/perf/util/bpf-userfuncs.h
new file mode 100644
index 000000000000..e920420237ee
--- /dev/null
+++ b/tools/perf/util/bpf-userfuncs.h
@@ -0,0 +1,19 @@
+#ifndef __BPF_USERFUNCS_H
+#define __BPF_USERFUNCS_H
+
+#include <bpf-userapi.h>
+
+static int (*bpfu_print)(const char *fmt, ...) =
+ (void *) BPF_FUNC_USER_print;
+static int (*bpfu_map_get_next_key)(void *map, void *key, void *value) =
+ (void *) BPF_FUNC_USER_bpf_map_get_next_key;
+static int (*bpfu_map_lookup_elem)(void *map, void *key, void *value) =
+ (void *) BPF_FUNC_USER_bpf_map_lookup_elem;
+
+#define print(fmt, ...) \
+({ \
+ char ____fmt[] = fmt; \
+ bpfu_print(____fmt, ##__VA_ARGS__); \
+})
+
+#endif /* __BPF_USERFUNCS_H */
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 12/13] perf bpf: Run begin/end programs
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
` (10 preceding siblings ...)
2018-03-12 9:43 ` [PATCH 11/13] perf bpf: Add helper header files Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 9:43 ` [PATCH 13/13] perf samples: Add syscall-count.c object Jiri Olsa
2018-03-12 11:17 ` [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
13 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Running begin and end programs for ebpf object.
Link: http://lkml.kernel.org/n/tip-ego7m00cr7sru8l5bjpjwwcm@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/builtin-bpf.c | 6 ++++
tools/perf/util/bpf-loader.c | 78 ++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/bpf-loader.h | 2 ++
3 files changed, 86 insertions(+)
diff --git a/tools/perf/builtin-bpf.c b/tools/perf/builtin-bpf.c
index 7065153a9577..1111e240e259 100644
--- a/tools/perf/builtin-bpf.c
+++ b/tools/perf/builtin-bpf.c
@@ -94,6 +94,10 @@ static int __cmd_bpf(int argc , const char **argv)
goto out_child;
}
+ err = bpf__run_begin(stdout);
+ if (err)
+ goto out_child;
+
if (forks) {
perf_evlist__start_workload(bpf.evlist);
@@ -115,6 +119,8 @@ static int __cmd_bpf(int argc , const char **argv)
child_pid = -1;
+ bpf__run_end(stdout);
+
out_child:
if (forks) {
if (workload_exec_errno) {
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index e59168153375..d5f9c3cd5280 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -9,6 +9,7 @@
#include <linux/bpf.h>
#include <bpf/libbpf.h>
#include <bpf/bpf.h>
+#include <bpf/interp.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@ -23,6 +24,7 @@
#include "strfilter.h"
#include "llvm-utils.h"
#include "c++/clang-c.h"
+#include "bpf-userapi.h"
#define DEFINE_PRINT_FN(name, level) \
static int libbpf_##name(const char *fmt, ...) \
@@ -1547,6 +1549,82 @@ int bpf__apply_obj_config(void)
return 0;
}
+struct interp {
+ struct bpf_interp in;
+ FILE *out;
+};
+
+static int bpf_interp_call_cb(struct bpf_interp *in,
+ u64 imm, u64 *regs)
+{
+ struct interp *interp = container_of(in, struct interp, in);
+ u64 dr;
+
+ switch (imm) {
+ case BPF_FUNC_USER_bpf_map_lookup_elem:
+ dr = bpf_map_lookup_elem((int) regs[1],
+ (void *) regs[2],
+ (void *) regs[3]);
+ break;
+ case BPF_FUNC_USER_bpf_map_get_next_key:
+ dr = bpf_map_get_next_key((int) regs[1],
+ (void *) regs[2],
+ (void *) regs[3]);
+ break;
+ case BPF_FUNC_USER_print:
+ dr = fprintf(interp->out, (const char *) regs[1],
+ regs[2], regs[3], regs[4], regs[5]);
+ fflush(interp->out);
+ break;
+ default:
+ return -1;
+ break;
+ };
+
+ regs[0] = dr;
+ regs[1] = 0xdeadbeef;
+ regs[2] = 0xdeadbeef;
+ regs[3] = 0xdeadbeef;
+ regs[4] = 0xdeadbeef;
+ return 0;
+}
+
+int bpf__run_begin(FILE *out)
+{
+ struct interp interp = {
+ .in.call_cb = bpf_interp_call_cb,
+ .out = out,
+ };
+ struct bpf_object *obj, *tmp;
+ int err;
+
+ bpf_object__for_each_safe(obj, tmp) {
+ err = bpf_object__run_begin(obj, &interp.in);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+int bpf__run_end(FILE *out)
+{
+ struct interp interp = {
+ .in.call_cb = bpf_interp_call_cb,
+ .out = out,
+ };
+ struct bpf_object *obj, *tmp;
+ int err;
+
+ bpf_object__for_each_safe(obj, tmp) {
+ err = bpf_object__run_end(obj, &interp.in);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
#define bpf__for_each_map(pos, obj, objtmp) \
bpf_object__for_each_safe(obj, objtmp) \
bpf_map__for_each(pos, obj)
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 8c2a494cab53..1ee4c3ca4927 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -87,6 +87,8 @@ int bpf__setup_stdout(struct perf_evlist *evlist);
int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err,
char *buf, size_t size);
+int bpf__run_begin(FILE *out);
+int bpf__run_end(FILE *out);
#else
#include <errno.h>
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 13/13] perf samples: Add syscall-count.c object
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
` (11 preceding siblings ...)
2018-03-12 9:43 ` [PATCH 12/13] perf bpf: Run begin/end programs Jiri Olsa
@ 2018-03-12 9:43 ` Jiri Olsa
2018-03-12 11:17 ` [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
13 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 9:43 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Adding syscall-count.c sample, that generates
syscall entry calls, like:
$ perf bpf -c samples/syscall-counts.c
LLVM: dumping samples/syscall-counts.o
$ sudo perf bpf -e samples/syscall-counts.o -a
BEGIN
^CEND
comm value
firefox 182
Socket Thread 8
InotifyEventThr 26
xmonad-x86_64-l 405
perf 45122
VoiceProcessThr 12
JS Watchdog 14
Chrome_~dThread 657
Softwar~cThread 474
Gecko_IOThread 489
stalonetray 8
mutt 410
Xorg 956
xchat 37
nm-applet 14
xscreensaver 170
Timer 1205
NetworkManager 25
rtkit-daemon 4
webrtc_audio_mo 24
Web Content 6889
IPDL Background 474
JS Helper 221
gkrellm 434
xterm 528
InputThread 793
Link: http://lkml.kernel.org/n/tip-9jsy0nnm8khn6e60fmwn4ei7@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/samples/syscall-counts.c | 61 +++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 tools/perf/samples/syscall-counts.c
diff --git a/tools/perf/samples/syscall-counts.c b/tools/perf/samples/syscall-counts.c
new file mode 100644
index 000000000000..e6de6c9fdb85
--- /dev/null
+++ b/tools/perf/samples/syscall-counts.c
@@ -0,0 +1,61 @@
+#include <uapi/linux/bpf.h>
+#include <bpf-helpers.h>
+#include <bpf-userfuncs.h>
+
+#define TASK_COMM_LEN 16
+
+char _license[] SEC("license") = "GPL";
+int _version SEC("version") = LINUX_VERSION_CODE;
+
+struct key_t {
+ char comm[TASK_COMM_LEN];
+};
+
+struct bpf_map_def SEC("maps") counts_map = {
+ .type = BPF_MAP_TYPE_HASH,
+ .key_size = sizeof(struct key_t),
+ .value_size = sizeof(u64),
+ .max_entries = 100,
+};
+
+SEC("raw_syscalls:sys_enter")
+int func(void *ctx)
+{
+ u64 *val, one = 1;
+ struct key_t key;
+ char comm[TASK_COMM_LEN];
+
+ bpf_get_current_comm(&key.comm, sizeof(comm));
+
+ val = bpf_map_lookup_elem(&counts_map, &key);
+ if (val)
+ (*val)++;
+ else
+ bpf_map_update_elem(&counts_map, &key, &one, BPF_NOEXIST);
+
+ return 0;
+}
+
+int BEGIN(void)
+{
+ print("BEGIN\n");
+ return 0;
+}
+
+void END(void)
+{
+ struct key_t key = {}, next_key;
+ u64 value;
+ int i = 0;
+
+ print("END\n");
+ print("\n comm value\n");
+
+ while (bpfu_map_get_next_key(&counts_map, &key, &next_key) == 0) {
+ if (bpfu_map_lookup_elem(&counts_map, &next_key, &value))
+ continue;
+
+ print("%18s %16lu\n", next_key.comm, value);
+ key = next_key;
+ }
+}
--
2.13.6
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [RFC 00/13] perf bpf: Add support to run BEGIN/END code
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
` (12 preceding siblings ...)
2018-03-12 9:43 ` [PATCH 13/13] perf samples: Add syscall-count.c object Jiri Olsa
@ 2018-03-12 11:17 ` Jiri Olsa
2018-03-12 13:56 ` Arnaldo Carvalho de Melo
13 siblings, 1 reply; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 11:17 UTC (permalink / raw)
To: Jiri Olsa
Cc: Arnaldo Carvalho de Melo, Brendan Gregg, Stanislav Kozina,
Frank Ch. Eigler, Will Cohen, Eugene Syromiatnikov,
Jerome Marchand, lkml, Ingo Molnar, Namhyung Kim, David Ahern,
Alexander Shishkin, Peter Zijlstra, Wang Nan, Alexei Starovoitov
adding Alexei and Wang to the loop
On Mon, Mar 12, 2018 at 10:43:00AM +0100, Jiri Olsa wrote:
> hi,
> this is *RFC* and the following patchset is very rough
> and ugly 'prove of concept'-kind-of-toy code. I'm mostly
> interested in opinions about if this could be useful in
> your current eBPF usage.
>
> Currently we can load eBPF code within the record command
> and attach it to event. We have 2 ways of communicating
> the data back to user: bpf-output event that goes to
> perf.data or 'trace_printk' output in tracefs buffer.
>
> AFAICS we're not covering quite large usage base that runs
> code before and once the probe is finished to setup, collect
> and display the collected data.
>
> This patchset is adding support to run BEGIN and END
> code snipets before and after eBPF probe is loaded.
>
> This allow to write 'collecting' code in eBPF object,
> like in the attached example (it's also part of the
> patchset).
>
> This patchset also adds 'bpf' command to ease up the
> loading of eBPF files with options for compilation
> and disassembly of eBPF objects:
>
> $ perf bpf -c samples/syscall-counts.c
> LLVM: dumping samples/syscall-counts.o
>
> $ perf bpf -d samples/syscall-counts.o | head
> Disassembly of raw_syscalls:sys_enter:
> 0: (b7) r1 = 1
> b7 01 00 00 01 00 00 00
> 1: (7b) *(u64 *)(r10 -8) = r1
> 7b 1a f8 ff 00 00 00 00
> 2: (bf) r6 = r10
> ...
>
> $ sudo perf bpf -e samples/syscall-counts.o -a
> BEGIN
> ^CEND
> comm value
> firefox 182
> Socket Thread 8
> InotifyEventThr 26
> xmonad-x86_64-l 405
> ...
>
> The patchset is also available in here:
> https://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
> perf/bpf
>
> So far I need following following lines in .perfconfig to run this:
> [llvm]
> kbuild-dir=/home/jolsa/kernel/linux-perf
> clang-opt=-I/home/jolsa/kernel/linux-perf/tools/perf/util
>
>
> thoughts? ;-) thanks,
> jirka
>
>
> Cc: Brendan Gregg <bgregg@netflix.com>
> Cc: Stanislav Kozina <skozina@redhat.com>
> Cc: "Frank Ch. Eigler" <fche@redhat.com>
> Cc: Will Cohen <wcohen@redhat.com>
> Cc: Eugene Syromiatnikov <esyromia@redhat.com>
> Cc: Jerome Marchand <jmarchan@redhat.com>
>
> ---
> #include <uapi/linux/bpf.h>
> #include <bpf-helpers.h>
> #include <bpf-userfuncs.h>
>
> #define TASK_COMM_LEN 16
>
> char _license[] SEC("license") = "GPL";
> int _version SEC("version") = LINUX_VERSION_CODE;
>
> struct key_t {
> char comm[TASK_COMM_LEN];
> };
>
> struct bpf_map_def SEC("maps") counts_map = {
> .type = BPF_MAP_TYPE_HASH,
> .key_size = sizeof(struct key_t),
> .value_size = sizeof(u64),
> .max_entries = 100,
> };
>
> SEC("raw_syscalls:sys_enter")
> int func(void *ctx)
> {
> u64 *val, one = 1;
> struct key_t key;
> char comm[TASK_COMM_LEN];
>
> bpf_get_current_comm(&key.comm, sizeof(comm));
>
> val = bpf_map_lookup_elem(&counts_map, &key);
> if (val)
> (*val)++;
> else
> bpf_map_update_elem(&counts_map, &key, &one, BPF_NOEXIST);
>
> return 0;
> }
>
> int BEGIN(void)
> {
> print("BEGIN\n");
> return 0;
> }
>
> void END(void)
> {
> struct key_t key = {}, next_key;
> u64 value;
> int i = 0;
>
> print("END\n");
> print("\n comm value\n");
>
> while (bpfu_map_get_next_key(&counts_map, &key, &next_key) == 0) {
> if (bpfu_map_lookup_elem(&counts_map, &next_key, &value))
> continue;
>
> print("%18s %16lu\n", next_key.comm, value);
> key = next_key;
> }
> }
>
> ---
> Jiri Olsa (13):
> lib bpf: Add bpf_program__insns function
> perf tools: Display ebpf compiling command in debug output
> perf tools: Add bpf command
> perf tools: Add bpf__compile function
> perf bpf: Add compile option
> perf bpf: Add disasm option
> libbpf: Make bpf_program__next skip .text section
> libbpf: Collect begin/end .text functions
> libbpf: Add bpf_insn__interpret function
> libbpf: Add bpf_object__run_(begin|end) functions
> perf bpf: Add helper header files
> perf bpf: Run begin/end programs
> perf samples: Add syscall-count.c object
>
> tools/lib/bpf/Build | 2 +-
> tools/lib/bpf/interp.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> tools/lib/bpf/libbpf.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++--
> tools/lib/bpf/libbpf.h | 7 +++
> tools/perf/Build | 7 +++
> tools/perf/Makefile.config | 1 +
> tools/perf/builtin-bpf.c | 319 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> tools/perf/builtin.h | 1 +
> tools/perf/command-list.txt | 1 +
> tools/perf/perf.c | 1 +
> tools/perf/samples/syscall-counts.c | 61 ++++++++++++++++++++++++
> tools/perf/util/bpf-helpers.h | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> tools/perf/util/bpf-loader.c | 124 ++++++++++++++++++++++++++++++++++++++++++++-----
> tools/perf/util/bpf-loader.h | 4 ++
> tools/perf/util/bpf-userapi.h | 11 +++++
> tools/perf/util/bpf-userfuncs.h | 19 ++++++++
> tools/perf/util/llvm-utils.c | 14 ++++++
> 17 files changed, 1173 insertions(+), 15 deletions(-)
> create mode 100644 tools/lib/bpf/interp.c
> create mode 100644 tools/perf/builtin-bpf.c
> create mode 100644 tools/perf/samples/syscall-counts.c
> create mode 100644 tools/perf/util/bpf-helpers.h
> create mode 100644 tools/perf/util/bpf-userapi.h
> create mode 100644 tools/perf/util/bpf-userfuncs.h
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC 00/13] perf bpf: Add support to run BEGIN/END code
2018-03-12 11:17 ` [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
@ 2018-03-12 13:56 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 27+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-03-12 13:56 UTC (permalink / raw)
To: Jiri Olsa
Cc: Brendan Gregg, Stanislav Kozina, Frank Ch. Eigler, Will Cohen,
Eugene Syromiatnikov, Jerome Marchand, lkml, Ingo Molnar,
Namhyung Kim, David Ahern, Alexander Shishkin, Peter Zijlstra,
Jiri Olsa, Wang Nan, Alexei Starovoitov
Em Mon, Mar 12, 2018 at 12:17:05PM +0100, Jiri Olsa escreveu:
> adding Alexei and Wang to the loop
>
> On Mon, Mar 12, 2018 at 10:43:00AM +0100, Jiri Olsa wrote:
> > hi,
> > this is *RFC* and the following patchset is very rough
> > and ugly 'prove of concept'-kind-of-toy code. I'm mostly
> > interested in opinions about if this could be useful in
> > your current eBPF usage.
> >
> > Currently we can load eBPF code within the record command
> > and attach it to event. We have 2 ways of communicating
> > the data back to user: bpf-output event that goes to
> > perf.data or 'trace_printk' output in tracefs buffer.
> >
> > AFAICS we're not covering quite large usage base that runs
> > code before and once the probe is finished to setup, collect
> > and display the collected data.
> >
> > This patchset is adding support to run BEGIN and END
> > code snipets before and after eBPF probe is loaded.
Right, with all the code that Wang contributed, and reusing that
begin/end code from systemtap, it was easy to do it, not that much code
added, so I don't see a reason for this not to be merged.
On top of this patchset, I think that the restricted C code that is used
to write the eBPF utilities should be simplified, I've toyed with this
from time to time, for instance:
[root@jouet bpf]# cat o_cloexec.c
#include "bpf.h"
#include "stdio.h"
#define O_CLOEXEC 0x80000
int syscall_enter(openat)
{
char filename[256];
int flags = syscall_field_int(flags, 32);
int len = syscall_field_str(filename, 24);
if (!(flags & O_CLOEXEC))
return 0;
perf_stdout(filename, len);
return 1;
}
[root@jouet bpf]# perf trace -e openat,o_cloexec.c
0.573 ( ): __bpf_stdout__:/etc/ld.so.cache....)
0.576 ( ): syscalls:sys_enter_openat:dfd: 0xffffffffffffff9c, filename: 0x7fc4de411563, flags: 0x00080000, mode: 0x00000000)
0.579 ( 0.013 ms): sh/17728 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC ) = 3
0.620 ( ): __bpf_stdout__:/lib64/libtinfo.so.6........)
0.622 ( ): syscalls:sys_enter_openat:dfd: 0xffffffffffffff9c, filename: 0x7fc4de619ce0, flags: 0x00080000, mode: 0x00000000)
0.624 ( 0.013 ms): sh/17728 openat(dfd: CWD, filename: /lib64/libtinfo.so.6, flags: CLOEXEC ) = 3
0.705 ( ): __bpf_stdout__:/lib64/libdl.so.2...)
0.708 ( ): syscalls:sys_enter_openat:dfd: 0xffffffffffffff9c, filename: 0x7fc4de5ef4c0, flags: 0x00080000, mode: 0x00000000)
0.710 ( 0.058 ms): sh/17728 openat(dfd: CWD, filename: /lib64/libdl.so.2, flags: CLOEXEC ) = 3
0.852 ( ): __bpf_stdout__:/lib64/libc.so.6....)
0.857 ( ): syscalls:sys_enter_openat:dfd: 0xffffffffffffff9c, filename: 0x7fc4de5ef9a0, flags: 0x00080000, mode: 0x00000000)
0.860 ( 0.021 ms): sh/17728 openat(dfd: CWD, filename: /lib64/libc.so.6, flags: CLOEXEC ) = 3
^C
[root@jouet bpf]#
Hiding details such as:
[root@jouet bpf]# cat stdio.h
struct bpf_map_def SEC("maps") __bpf_stdout__ = {
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(u32),
.max_entries = __NR_CPUS__,
};
#define perf_stdout(from, len) \
perf_event_output(ctx, &__bpf_stdout__, BPF_F_CURRENT_CPU, \
&from, len & (sizeof(from) - 1));
[root@jouet bpf]#
That 'perf trace' will setup "bpf_output" event, etc.
And the other macros:
#define SEC(NAME) __attribute__((section(NAME), used))
#define pid_map(name, value_type) \
struct bpf_map_def SEC("maps") name = { \
.type = BPF_MAP_TYPE_HASH, \
.key_size = sizeof(u64), \
.value_size = sizeof(value_type), \
.max_entries = 500, \
}
#define syscall_enter(name) \
SEC("syscalls:sys_enter_" #name) syscall_enter_ ## name(void *ctx)
#define syscall_exit(name) \
SEC("syscalls:sys_exit_" #name) syscall_exit_ ## name(void *ctx)
#define syscall_field_str(field, offset) \
({ char *__ptr = *((char **)(ctx + offset)); \
bpf_probe_read_str(field, sizeof(field), __ptr); })
#define syscall_field_int(field, offset) \
({ int *__ptr = (int *)(ctx + offset); \
bpf_probe_read(&field, sizeof(field), __ptr); field; }
While this hides some of the details, it still hardcodes the offset, so
should be used that way, I was trying to read about clang internals to
do some preprocessing trick that would automagically make the tracepoint
fields accessible as local variables, reading the tracepoint format
files from the running system or from the description stored in the
perf.data header, when running these things on perf.data files.
- Arnaldo
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 02/13] perf tools: Display ebpf compiling command in debug output
2018-03-12 9:43 ` [PATCH 02/13] perf tools: Display ebpf compiling command in debug output Jiri Olsa
@ 2018-03-12 14:24 ` Arnaldo Carvalho de Melo
2018-03-20 6:29 ` [tip:perf/core] perf llvm: Display eBPF " tip-bot for Jiri Olsa
1 sibling, 0 replies; 27+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-03-12 14:24 UTC (permalink / raw)
To: Jiri Olsa
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Em Mon, Mar 12, 2018 at 10:43:02AM +0100, Jiri Olsa escreveu:
> In addition to template, display also the real compile
> command line with all the variables substituted.
>
> llvm compiling command template: $CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS ...
> llvm compiling command : /usr/bin/clang -D__KERNEL__ -D__NR_CPUS__=24 -DLINUX_VERSION_CODE=0x41000 ...
Useful, applied.
- Arnaldo
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 09/13] libbpf: Add bpf_insn__interpret function
2018-03-12 9:43 ` [PATCH 09/13] libbpf: Add bpf_insn__interpret function Jiri Olsa
@ 2018-03-12 15:44 ` Arnaldo Carvalho de Melo
2018-03-12 15:53 ` Jiri Olsa
0 siblings, 1 reply; 27+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-03-12 15:44 UTC (permalink / raw)
To: Jiri Olsa
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Em Mon, Mar 12, 2018 at 10:43:09AM +0100, Jiri Olsa escreveu:
> Adding bpf_insn__interpret function to run ebpf program
> in user space.
>
> It's 'borrowed' from systemtap code, I still need to figure
> the proper credits, that will go to the file header in case
> this would ever go in.
What is the license? GPL?
> Link: http://lkml.kernel.org/n/tip-qqxsyw6imdisj3dydd6e21y7@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
>
> +++ b/tools/lib/bpf/Build
> @@ -1 +1 @@
> -libbpf-y := libbpf.o bpf.o nlattr.o
> +libbpf-y := libbpf.o bpf.o nlattr.o interp.o
> diff --git a/tools/lib/bpf/interp.c b/tools/lib/bpf/interp.c
> new file mode 100644
> index 000000000000..2ceb6a0836c3
> --- /dev/null
> +++ b/tools/lib/bpf/interp.c
> @@ -0,0 +1,245 @@
> +#include <uapi/linux/bpf.h>
> +#include <stdlib.h>
> +#include "interp.h"
> +
> +u64 bpf_interp__run(struct bpf_interp *interp)
> +{
<SNIP>
> +
> + case BPF_JMP | BPF_EXIT:
> + return regs[0];
> +
> + default:
> + abort();
And this should be converted to returning some error that the users can
tell the user using whatever UI (TUI, etc).
> + }
> +
> + regs[i->dst_reg] = dr;
> + nowrite:
> + i++;
> + }
> +
> + return 0;
> +}
> --
> 2.13.6
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 09/13] libbpf: Add bpf_insn__interpret function
2018-03-12 15:44 ` Arnaldo Carvalho de Melo
@ 2018-03-12 15:53 ` Jiri Olsa
0 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 15:53 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Jiri Olsa, lkml, Ingo Molnar, Namhyung Kim, David Ahern,
Alexander Shishkin, Peter Zijlstra
On Mon, Mar 12, 2018 at 12:44:03PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Mon, Mar 12, 2018 at 10:43:09AM +0100, Jiri Olsa escreveu:
> > Adding bpf_insn__interpret function to run ebpf program
> > in user space.
> >
> > It's 'borrowed' from systemtap code, I still need to figure
> > the proper credits, that will go to the file header in case
> > this would ever go in.
>
> What is the license? GPL?
yes GPLv2
>
> > Link: http://lkml.kernel.org/n/tip-qqxsyw6imdisj3dydd6e21y7@git.kernel.org
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> >
> > +++ b/tools/lib/bpf/Build
> > @@ -1 +1 @@
> > -libbpf-y := libbpf.o bpf.o nlattr.o
> > +libbpf-y := libbpf.o bpf.o nlattr.o interp.o
> > diff --git a/tools/lib/bpf/interp.c b/tools/lib/bpf/interp.c
> > new file mode 100644
> > index 000000000000..2ceb6a0836c3
> > --- /dev/null
> > +++ b/tools/lib/bpf/interp.c
> > @@ -0,0 +1,245 @@
> > +#include <uapi/linux/bpf.h>
> > +#include <stdlib.h>
> > +#include "interp.h"
> > +
> > +u64 bpf_interp__run(struct bpf_interp *interp)
> > +{
> <SNIP>
> > +
> > + case BPF_JMP | BPF_EXIT:
> > + return regs[0];
> > +
> > + default:
> > + abort();
>
> And this should be converted to returning some error that the users can
> tell the user using whatever UI (TUI, etc).
right, I want to get rid of all abort calls, I think there's one more
jirka
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 11/13] perf bpf: Add helper header files
2018-03-12 9:43 ` [PATCH 11/13] perf bpf: Add helper header files Jiri Olsa
@ 2018-03-12 18:44 ` Alexei Starovoitov
2018-03-12 19:06 ` Arnaldo Carvalho de Melo
2018-03-12 19:20 ` Jiri Olsa
2018-03-13 1:35 ` Arnaldo Carvalho de Melo
1 sibling, 2 replies; 27+ messages in thread
From: Alexei Starovoitov @ 2018-03-12 18:44 UTC (permalink / raw)
To: Jiri Olsa
Cc: Arnaldo Carvalho de Melo, lkml, Ingo Molnar, Namhyung Kim,
David Ahern, Alexander Shishkin, Peter Zijlstra, Daniel Borkmann,
Wangnan
On Mon, Mar 12, 2018 at 10:43:11AM +0100, Jiri Olsa wrote:
> diff --git a/tools/perf/util/bpf-userapi.h b/tools/perf/util/bpf-userapi.h
> new file mode 100644
> index 000000000000..63f2b4c13a5c
> --- /dev/null
> +++ b/tools/perf/util/bpf-userapi.h
> @@ -0,0 +1,11 @@
> +#ifndef __BPF_USERAPI_H
> +#define __BPF_USERAPI_H
> +
> +enum {
> + BPF_FUNC_USER_START = 10000,
> + BPF_FUNC_USER_print = BPF_FUNC_USER_START,
> + BPF_FUNC_USER_bpf_map_get_next_key,
> + BPF_FUNC_USER_bpf_map_lookup_elem,
> +};
> +
> +#endif /* __BPF_USERFUNCS_H */
> diff --git a/tools/perf/util/bpf-userfuncs.h b/tools/perf/util/bpf-userfuncs.h
> new file mode 100644
> index 000000000000..e920420237ee
> --- /dev/null
> +++ b/tools/perf/util/bpf-userfuncs.h
> @@ -0,0 +1,19 @@
> +#ifndef __BPF_USERFUNCS_H
> +#define __BPF_USERFUNCS_H
> +
> +#include <bpf-userapi.h>
> +
> +static int (*bpfu_print)(const char *fmt, ...) =
> + (void *) BPF_FUNC_USER_print;
> +static int (*bpfu_map_get_next_key)(void *map, void *key, void *value) =
> + (void *) BPF_FUNC_USER_bpf_map_get_next_key;
> +static int (*bpfu_map_lookup_elem)(void *map, void *key, void *value) =
> + (void *) BPF_FUNC_USER_bpf_map_lookup_elem;
> +
> +#define print(fmt, ...) \
> +({ \
> + char ____fmt[] = fmt; \
> + bpfu_print(____fmt, ##__VA_ARGS__); \
> +})
since there is no verifier for this user space bpf interpreter
there is no need to restrict what BEGIN/END progs can do and can call.
llvm will happily compile any C code into bpf instructions.
With little bit of elf magic it's possible to let it call any libc
function instead of only 3 above.
perf loader will see bpf_call into normal printf, memcpy, memcmp, etc
then during the loading need to associate symbol with actual address
of these functions inside perf binary and let call_cb do the call.
I think this way begin/end will be much more powerful and useful.
Potentially allowing some of the bcc scripts to be written this way.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 11/13] perf bpf: Add helper header files
2018-03-12 18:44 ` Alexei Starovoitov
@ 2018-03-12 19:06 ` Arnaldo Carvalho de Melo
2018-03-12 19:20 ` Jiri Olsa
1 sibling, 0 replies; 27+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-03-12 19:06 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Jiri Olsa, lkml, Ingo Molnar, Namhyung Kim, David Ahern,
Alexander Shishkin, Peter Zijlstra, Daniel Borkmann, Wangnan
Em Mon, Mar 12, 2018 at 11:44:57AM -0700, Alexei Starovoitov escreveu:
> On Mon, Mar 12, 2018 at 10:43:11AM +0100, Jiri Olsa wrote:
> > diff --git a/tools/perf/util/bpf-userapi.h b/tools/perf/util/bpf-userapi.h
> > new file mode 100644
> > index 000000000000..63f2b4c13a5c
> > --- /dev/null
> > +++ b/tools/perf/util/bpf-userapi.h
> > @@ -0,0 +1,11 @@
> > +#ifndef __BPF_USERAPI_H
> > +#define __BPF_USERAPI_H
> > +
> > +enum {
> > + BPF_FUNC_USER_START = 10000,
> > + BPF_FUNC_USER_print = BPF_FUNC_USER_START,
> > + BPF_FUNC_USER_bpf_map_get_next_key,
> > + BPF_FUNC_USER_bpf_map_lookup_elem,
> > +};
> > +
> > +#endif /* __BPF_USERFUNCS_H */
> > diff --git a/tools/perf/util/bpf-userfuncs.h b/tools/perf/util/bpf-userfuncs.h
> > new file mode 100644
> > index 000000000000..e920420237ee
> > --- /dev/null
> > +++ b/tools/perf/util/bpf-userfuncs.h
> > @@ -0,0 +1,19 @@
> > +#ifndef __BPF_USERFUNCS_H
> > +#define __BPF_USERFUNCS_H
> > +
> > +#include <bpf-userapi.h>
> > +
> > +static int (*bpfu_print)(const char *fmt, ...) =
> > + (void *) BPF_FUNC_USER_print;
> > +static int (*bpfu_map_get_next_key)(void *map, void *key, void *value) =
> > + (void *) BPF_FUNC_USER_bpf_map_get_next_key;
> > +static int (*bpfu_map_lookup_elem)(void *map, void *key, void *value) =
> > + (void *) BPF_FUNC_USER_bpf_map_lookup_elem;
> > +
> > +#define print(fmt, ...) \
> > +({ \
> > + char ____fmt[] = fmt; \
> > + bpfu_print(____fmt, ##__VA_ARGS__); \
> > +})
>
> since there is no verifier for this user space bpf interpreter
> there is no need to restrict what BEGIN/END progs can do and can call.
> llvm will happily compile any C code into bpf instructions.
> With little bit of elf magic it's possible to let it call any libc
> function instead of only 3 above.
> perf loader will see bpf_call into normal printf, memcpy, memcmp, etc
> then during the loading need to associate symbol with actual address
> of these functions inside perf binary and let call_cb do the call.
> I think this way begin/end will be much more powerful and useful.
> Potentially allowing some of the bcc scripts to be written this way.
Yeah, what is in perf right now, i.e. symbol resolution, rbtree, etc
provides a really nice lib for use in these scripts.
- Arnaldo
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 11/13] perf bpf: Add helper header files
2018-03-12 18:44 ` Alexei Starovoitov
2018-03-12 19:06 ` Arnaldo Carvalho de Melo
@ 2018-03-12 19:20 ` Jiri Olsa
2018-03-12 19:25 ` Arnaldo Carvalho de Melo
1 sibling, 1 reply; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 19:20 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Jiri Olsa, Arnaldo Carvalho de Melo, lkml, Ingo Molnar,
Namhyung Kim, David Ahern, Alexander Shishkin, Peter Zijlstra,
Daniel Borkmann, Wangnan
On Mon, Mar 12, 2018 at 11:44:57AM -0700, Alexei Starovoitov wrote:
> On Mon, Mar 12, 2018 at 10:43:11AM +0100, Jiri Olsa wrote:
> > diff --git a/tools/perf/util/bpf-userapi.h b/tools/perf/util/bpf-userapi.h
> > new file mode 100644
> > index 000000000000..63f2b4c13a5c
> > --- /dev/null
> > +++ b/tools/perf/util/bpf-userapi.h
> > @@ -0,0 +1,11 @@
> > +#ifndef __BPF_USERAPI_H
> > +#define __BPF_USERAPI_H
> > +
> > +enum {
> > + BPF_FUNC_USER_START = 10000,
> > + BPF_FUNC_USER_print = BPF_FUNC_USER_START,
> > + BPF_FUNC_USER_bpf_map_get_next_key,
> > + BPF_FUNC_USER_bpf_map_lookup_elem,
> > +};
> > +
> > +#endif /* __BPF_USERFUNCS_H */
> > diff --git a/tools/perf/util/bpf-userfuncs.h b/tools/perf/util/bpf-userfuncs.h
> > new file mode 100644
> > index 000000000000..e920420237ee
> > --- /dev/null
> > +++ b/tools/perf/util/bpf-userfuncs.h
> > @@ -0,0 +1,19 @@
> > +#ifndef __BPF_USERFUNCS_H
> > +#define __BPF_USERFUNCS_H
> > +
> > +#include <bpf-userapi.h>
> > +
> > +static int (*bpfu_print)(const char *fmt, ...) =
> > + (void *) BPF_FUNC_USER_print;
> > +static int (*bpfu_map_get_next_key)(void *map, void *key, void *value) =
> > + (void *) BPF_FUNC_USER_bpf_map_get_next_key;
> > +static int (*bpfu_map_lookup_elem)(void *map, void *key, void *value) =
> > + (void *) BPF_FUNC_USER_bpf_map_lookup_elem;
> > +
> > +#define print(fmt, ...) \
> > +({ \
> > + char ____fmt[] = fmt; \
> > + bpfu_print(____fmt, ##__VA_ARGS__); \
> > +})
>
> since there is no verifier for this user space bpf interpreter
> there is no need to restrict what BEGIN/END progs can do and can call.
> llvm will happily compile any C code into bpf instructions.
> With little bit of elf magic it's possible to let it call any libc
> function instead of only 3 above.
> perf loader will see bpf_call into normal printf, memcpy, memcmp, etc
> then during the loading need to associate symbol with actual address
> of these functions inside perf binary and let call_cb do the call.
right, I kept this way, because it was already there for kernel,
so it was fast to write ;-)
but it's true we could leave it symbol based and have some sort of
dynamic loader behaviour.. but we'd need to sort out passing the
arguments in some generic form.. I'll check on that
thanks,
jirka
> I think this way begin/end will be much more powerful and useful.
> Potentially allowing some of the bcc scripts to be written this way.
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 11/13] perf bpf: Add helper header files
2018-03-12 19:20 ` Jiri Olsa
@ 2018-03-12 19:25 ` Arnaldo Carvalho de Melo
2018-03-12 22:32 ` Jiri Olsa
0 siblings, 1 reply; 27+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-03-12 19:25 UTC (permalink / raw)
To: Jiri Olsa
Cc: Alexei Starovoitov, Jiri Olsa, lkml, Ingo Molnar, Namhyung Kim,
David Ahern, Alexander Shishkin, Peter Zijlstra, Daniel Borkmann,
Wangnan
Em Mon, Mar 12, 2018 at 08:20:20PM +0100, Jiri Olsa escreveu:
> On Mon, Mar 12, 2018 at 11:44:57AM -0700, Alexei Starovoitov wrote:
> > On Mon, Mar 12, 2018 at 10:43:11AM +0100, Jiri Olsa wrote:
> > > diff --git a/tools/perf/util/bpf-userapi.h b/tools/perf/util/bpf-userapi.h
> > > new file mode 100644
> > > index 000000000000..63f2b4c13a5c
> > > --- /dev/null
> > > +++ b/tools/perf/util/bpf-userapi.h
> > > @@ -0,0 +1,11 @@
> > > +#ifndef __BPF_USERAPI_H
> > > +#define __BPF_USERAPI_H
> > > +
> > > +enum {
> > > + BPF_FUNC_USER_START = 10000,
> > > + BPF_FUNC_USER_print = BPF_FUNC_USER_START,
> > > + BPF_FUNC_USER_bpf_map_get_next_key,
> > > + BPF_FUNC_USER_bpf_map_lookup_elem,
> > > +};
> > > +
> > > +#endif /* __BPF_USERFUNCS_H */
> > > diff --git a/tools/perf/util/bpf-userfuncs.h b/tools/perf/util/bpf-userfuncs.h
> > > new file mode 100644
> > > index 000000000000..e920420237ee
> > > --- /dev/null
> > > +++ b/tools/perf/util/bpf-userfuncs.h
> > > @@ -0,0 +1,19 @@
> > > +#ifndef __BPF_USERFUNCS_H
> > > +#define __BPF_USERFUNCS_H
> > > +
> > > +#include <bpf-userapi.h>
> > > +
> > > +static int (*bpfu_print)(const char *fmt, ...) =
> > > + (void *) BPF_FUNC_USER_print;
> > > +static int (*bpfu_map_get_next_key)(void *map, void *key, void *value) =
> > > + (void *) BPF_FUNC_USER_bpf_map_get_next_key;
> > > +static int (*bpfu_map_lookup_elem)(void *map, void *key, void *value) =
> > > + (void *) BPF_FUNC_USER_bpf_map_lookup_elem;
> > > +
> > > +#define print(fmt, ...) \
> > > +({ \
> > > + char ____fmt[] = fmt; \
> > > + bpfu_print(____fmt, ##__VA_ARGS__); \
> > > +})
> >
> > since there is no verifier for this user space bpf interpreter
> > there is no need to restrict what BEGIN/END progs can do and can call.
> > llvm will happily compile any C code into bpf instructions.
> > With little bit of elf magic it's possible to let it call any libc
> > function instead of only 3 above.
> > perf loader will see bpf_call into normal printf, memcpy, memcmp, etc
> > then during the loading need to associate symbol with actual address
> > of these functions inside perf binary and let call_cb do the call.
>
> right, I kept this way, because it was already there for kernel,
> so it was fast to write ;-)
>
> but it's true we could leave it symbol based and have some sort of
> dynamic loader behaviour.. but we'd need to sort out passing the
> arguments in some generic form.. I'll check on that
Does this answer it or am I missing something?
Documentation/bpf/bpf_design_QA.txt
Q: Is BPF a generic virtual machine ?
A: NO.
BPF is generic instruction set _with_ C calling convention.
Q: Why C calling convention was chosen?
A: Because BPF programs are designed to run in the linux kernel
which is written in C, hence BPF defines instruction set compatible
with two most used architectures x64 and arm64 (and takes into
consideration important quirks of other architectures) and
defines calling convention that is compatible with C calling
convention of the linux kernel on those architectures.
- Arnaldo
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 11/13] perf bpf: Add helper header files
2018-03-12 19:25 ` Arnaldo Carvalho de Melo
@ 2018-03-12 22:32 ` Jiri Olsa
0 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-12 22:32 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Alexei Starovoitov, Jiri Olsa, lkml, Ingo Molnar, Namhyung Kim,
David Ahern, Alexander Shishkin, Peter Zijlstra, Daniel Borkmann,
Wangnan
On Mon, Mar 12, 2018 at 04:25:51PM -0300, Arnaldo Carvalho de Melo wrote:
SNIP
> >
> > right, I kept this way, because it was already there for kernel,
> > so it was fast to write ;-)
> >
> > but it's true we could leave it symbol based and have some sort of
> > dynamic loader behaviour.. but we'd need to sort out passing the
> > arguments in some generic form.. I'll check on that
>
> Does this answer it or am I missing something?
>
> Documentation/bpf/bpf_design_QA.txt
>
> Q: Is BPF a generic virtual machine ?
> A: NO.
>
> BPF is generic instruction set _with_ C calling convention.
>
> Q: Why C calling convention was chosen?
> A: Because BPF programs are designed to run in the linux kernel
> which is written in C, hence BPF defines instruction set compatible
> with two most used architectures x64 and arm64 (and takes into
> consideration important quirks of other architectures) and
> defines calling convention that is compatible with C calling
> convention of the linux kernel on those architectures.
hm right, but still we interpret the calls.. so we have to call
the function at the end
jirka
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 11/13] perf bpf: Add helper header files
2018-03-12 9:43 ` [PATCH 11/13] perf bpf: Add helper header files Jiri Olsa
2018-03-12 18:44 ` Alexei Starovoitov
@ 2018-03-13 1:35 ` Arnaldo Carvalho de Melo
2018-03-13 14:18 ` Jiri Olsa
1 sibling, 1 reply; 27+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-03-13 1:35 UTC (permalink / raw)
To: Jiri Olsa
Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
Peter Zijlstra
Em Mon, Mar 12, 2018 at 10:43:11AM +0100, Jiri Olsa escreveu:
> +#elif defined(__s390x__)
> + #define bpf_target_s930x
bpf_target_s390x
> +#elif defined(__aarch64__)
> + #define bpf_target_arm64
> +#elif defined(__mips__)
> + #define bpf_target_mips
> +#elif defined(__powerpc__)
> + #define bpf_target_powerpc
> +#elif defined(__sparc__)
> + #define bpf_target_sparc
> +#endif
> +#endif
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 11/13] perf bpf: Add helper header files
2018-03-13 1:35 ` Arnaldo Carvalho de Melo
@ 2018-03-13 14:18 ` Jiri Olsa
0 siblings, 0 replies; 27+ messages in thread
From: Jiri Olsa @ 2018-03-13 14:18 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Jiri Olsa, lkml, Ingo Molnar, Namhyung Kim, David Ahern,
Alexander Shishkin, Peter Zijlstra
On Mon, Mar 12, 2018 at 10:35:29PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Mon, Mar 12, 2018 at 10:43:11AM +0100, Jiri Olsa escreveu:
> > +#elif defined(__s390x__)
> > + #define bpf_target_s930x
>
> bpf_target_s390x
eagle eyes ;-) must be problem in samples/bpf where I stoled it from ;-)
thanks,
jirka
>
> > +#elif defined(__aarch64__)
> > + #define bpf_target_arm64
> > +#elif defined(__mips__)
> > + #define bpf_target_mips
> > +#elif defined(__powerpc__)
> > + #define bpf_target_powerpc
> > +#elif defined(__sparc__)
> > + #define bpf_target_sparc
> > +#endif
> > +#endif
^ permalink raw reply [flat|nested] 27+ messages in thread
* [tip:perf/core] perf llvm: Display eBPF compiling command in debug output
2018-03-12 9:43 ` [PATCH 02/13] perf tools: Display ebpf compiling command in debug output Jiri Olsa
2018-03-12 14:24 ` Arnaldo Carvalho de Melo
@ 2018-03-20 6:29 ` tip-bot for Jiri Olsa
1 sibling, 0 replies; 27+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-03-20 6:29 UTC (permalink / raw)
To: linux-tip-commits
Cc: alexander.shishkin, tglx, jolsa, acme, hpa, mingo, peterz,
dsahern, namhyung, linux-kernel
Commit-ID: 5eab5a7ee032acaab3da8fc95a3614fec14687ac
Gitweb: https://git.kernel.org/tip/5eab5a7ee032acaab3da8fc95a3614fec14687ac
Author: Jiri Olsa <jolsa@kernel.org>
AuthorDate: Mon, 12 Mar 2018 10:43:02 +0100
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 16 Mar 2018 13:56:12 -0300
perf llvm: Display eBPF compiling command in debug output
In addition to template, display also the real compile command line with
all the variables substituted.
llvm compiling command template: $CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS ...
llvm compiling command : /usr/bin/clang -D__KERNEL__ -D__NR_CPUS__=24 -DLINUX_VERSION_CODE=0x41000 ...
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180312094313.18738-3-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/llvm-utils.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 4952b429caa7..1cca0a2fa641 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -433,6 +433,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
char serr[STRERR_BUFSIZE];
char *kbuild_dir = NULL, *kbuild_include_opts = NULL;
const char *template = llvm_param.clang_bpf_cmd_template;
+ char *command_echo, *command_out;
if (path[0] != '-' && realpath(path, abspath) == NULL) {
err = errno;
@@ -487,6 +488,16 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
(path[0] == '-') ? path : abspath);
pr_debug("llvm compiling command template: %s\n", template);
+
+ if (asprintf(&command_echo, "echo -n \"%s\"", template) < 0)
+ goto errout;
+
+ err = read_from_pipe(command_echo, (void **) &command_out, NULL);
+ if (err)
+ goto errout;
+
+ pr_debug("llvm compiling command : %s\n", command_out);
+
err = read_from_pipe(template, &obj_buf, &obj_buf_sz);
if (err) {
pr_err("ERROR:\tunable to compile %s\n", path);
@@ -497,6 +508,8 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
goto errout;
}
+ free(command_echo);
+ free(command_out);
free(kbuild_dir);
free(kbuild_include_opts);
@@ -509,6 +522,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
*p_obj_buf_sz = obj_buf_sz;
return 0;
errout:
+ free(command_echo);
free(kbuild_dir);
free(kbuild_include_opts);
free(obj_buf);
^ permalink raw reply related [flat|nested] 27+ messages in thread
end of thread, other threads:[~2018-03-20 6:30 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-12 9:43 [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
2018-03-12 9:43 ` [PATCH 01/13] lib bpf: Add bpf_program__insns function Jiri Olsa
2018-03-12 9:43 ` [PATCH 02/13] perf tools: Display ebpf compiling command in debug output Jiri Olsa
2018-03-12 14:24 ` Arnaldo Carvalho de Melo
2018-03-20 6:29 ` [tip:perf/core] perf llvm: Display eBPF " tip-bot for Jiri Olsa
2018-03-12 9:43 ` [PATCH 03/13] perf tools: Add bpf command Jiri Olsa
2018-03-12 9:43 ` [PATCH 04/13] perf tools: Add bpf__compile function Jiri Olsa
2018-03-12 9:43 ` [PATCH 05/13] perf bpf: Add compile option Jiri Olsa
2018-03-12 9:43 ` [PATCH 06/13] perf bpf: Add disasm option Jiri Olsa
2018-03-12 9:43 ` [PATCH 07/13] libbpf: Make bpf_program__next skip .text section Jiri Olsa
2018-03-12 9:43 ` [PATCH 08/13] libbpf: Collect begin/end .text functions Jiri Olsa
2018-03-12 9:43 ` [PATCH 09/13] libbpf: Add bpf_insn__interpret function Jiri Olsa
2018-03-12 15:44 ` Arnaldo Carvalho de Melo
2018-03-12 15:53 ` Jiri Olsa
2018-03-12 9:43 ` [PATCH 10/13] libbpf: Add bpf_object__run_(begin|end) functions Jiri Olsa
2018-03-12 9:43 ` [PATCH 11/13] perf bpf: Add helper header files Jiri Olsa
2018-03-12 18:44 ` Alexei Starovoitov
2018-03-12 19:06 ` Arnaldo Carvalho de Melo
2018-03-12 19:20 ` Jiri Olsa
2018-03-12 19:25 ` Arnaldo Carvalho de Melo
2018-03-12 22:32 ` Jiri Olsa
2018-03-13 1:35 ` Arnaldo Carvalho de Melo
2018-03-13 14:18 ` Jiri Olsa
2018-03-12 9:43 ` [PATCH 12/13] perf bpf: Run begin/end programs Jiri Olsa
2018-03-12 9:43 ` [PATCH 13/13] perf samples: Add syscall-count.c object Jiri Olsa
2018-03-12 11:17 ` [RFC 00/13] perf bpf: Add support to run BEGIN/END code Jiri Olsa
2018-03-12 13:56 ` Arnaldo Carvalho de Melo
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.