lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20180312094313.18738-4-jolsa@kernel.org>
Date:   Mon, 12 Mar 2018 10:43:03 +0100
From:   Jiri Olsa <jolsa@...nel.org>
To:     Arnaldo Carvalho de Melo <acme@...nel.org>
Cc:     lkml <linux-kernel@...r.kernel.org>,
        Ingo Molnar <mingo@...nel.org>,
        Namhyung Kim <namhyung@...nel.org>,
        David Ahern <dsahern@...il.com>,
        Alexander Shishkin <alexander.shishkin@...ux.intel.com>,
        Peter Zijlstra <a.p.zijlstra@...llo.nl>
Subject: [PATCH 03/13] perf tools: Add bpf command

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@...nel.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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ