Commit 3d6dfae8 authored by Ian Rogers's avatar Ian Rogers Committed by Arnaldo Carvalho de Melo
Browse files

perf parse-events: Remove BPF event support



New features like the BPF --filter support in perf record have made the
BPF event functionality somewhat redundant. As shown by commit
fcb027c1a4f6 ("perf tools: Revert enable indices setting syntax for BPF
map") and commit 14e4b9f4 ("perf trace: Raw augmented syscalls fix
libbpf 1.0+ compatibility") the BPF event support hasn't been well
maintained and it adds considerable complexity in areas like event
parsing, not least as '/' is a separator for event modifiers as well as
in paths.

This patch removes support in the event parser for BPF events and then
the associated functions are removed. This leads to the removal of whole
source files like bpf-loader.c.  Removing support means that augmented
syscalls in perf trace is broken, this will be fixed in a later commit
adding support using BPF skeletons.

The removal of BPF events causes an unused label warning from flex
generated code, so update build to ignore it:

  ```
  util/parse-events-flex.c:2704:1: error: label ‘find_rule’ defined but not used [-Werror=unused-label]
  2704 | find_rule: /* we branch to this label when backing up */
  ```

Committer notes:

Extracted from a larger patch that was also removing the support for
linking with libllvm and libclang, that were an alternative to using an
external clang execution to compile the .c event source code into BPF
bytecode.

Testing it:

  # perf trace -e /home/acme/git/perf/tools/perf/examples/bpf/augmented_raw_syscalls.c
  event syntax error: '/home/acme/git/perf/tools/perf/examples/bpf/augmented_raw_syscalls.c'
                        \___ Bad event or PMU

  Unabled to find PMU or event on a PMU of 'home'

  Initial error:
  event syntax error: '/home/acme/git/perf/tools/perf/examples/bpf/augmented_raw_syscalls.c'
                        \___ Cannot find PMU `home'. Missing kernel support?
  Run 'perf list' for a list of valid events

   Usage: perf trace [<options>] [<command>]
      or: perf trace [<options>] -- <command> [<options>]
      or: perf trace record [<options>] [<command>]
      or: perf trace record [<options>] -- <command> [<options>]

      -e, --event <event>   event/syscall selector. use 'perf list' to list available events
  #

Signed-off-by: default avatarIan Rogers <irogers@google.com>
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Carsten Haitzler <carsten.haitzler@arm.com>
Cc: Eduard Zingerman <eddyz87@gmail.com>
Cc: Fangrui Song <maskray@google.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
Cc: Tom Rix <trix@redhat.com>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: Wang ShaoBo <bobo.shaobowang@huawei.com>
Cc: Yang Jihong <yangjihong1@huawei.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: YueHaibing <yuehaibing@huawei.com>
Cc: bpf@vger.kernel.org
Cc: llvm@lists.linux.dev
Link: https://lore.kernel.org/r/20230810184853.2860737-2-irogers@google.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>

Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 56b11a21
Loading
Loading
Loading
Loading
+0 −33
Original line number Diff line number Diff line
@@ -125,9 +125,6 @@ Given a $HOME/.perfconfig like this:
		group = true
		skip-empty = true

	[llvm]
		dump-obj = true
		clang-opt = -g

You can hide source code of annotate feature setting the config to false with

@@ -657,36 +654,6 @@ ftrace.*::
		-F option is not specified. Possible values are 'function' and
		'function_graph'.

llvm.*::
	llvm.clang-path::
		Path to clang. If omit, search it from $PATH.

	llvm.clang-bpf-cmd-template::
		Cmdline template. Below lines show its default value. Environment
		variable is used to pass options.
		"$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
		"-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE "	\
		"$CLANG_OPTIONS $PERF_BPF_INC_OPTIONS $KERNEL_INC_OPTIONS " \
		"-Wno-unused-value -Wno-pointer-sign "		\
		"-working-directory $WORKING_DIR "		\
		"-c \"$CLANG_SOURCE\" --target=bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE"

	llvm.clang-opt::
		Options passed to clang.

	llvm.kbuild-dir::
		kbuild directory. If not set, use /lib/modules/`uname -r`/build.
		If set to "" deliberately, skip kernel header auto-detector.

	llvm.kbuild-opts::
		Options passed to 'make' when detecting kernel header options.

	llvm.dump-obj::
		Enable perf dump BPF object files compiled by LLVM.

	llvm.opts::
		Options passed to llc.

samples.*::

	samples.context::
+0 −22
Original line number Diff line number Diff line
@@ -99,20 +99,6 @@ OPTIONS
          If you want to profile write accesses in [0x1000~1008), just set
          'mem:0x1000/8:w'.

        - a BPF source file (ending in .c) or a precompiled object file (ending
          in .o) selects one or more BPF events.
          The BPF program can attach to various perf events based on the ELF section
          names.

          When processing a '.c' file, perf searches an installed LLVM to compile it
          into an object file first. Optional clang options can be passed via the
          '--clang-opt' command line option, e.g.:

            perf record --clang-opt "-DLINUX_VERSION_CODE=0x50000" \
                        -e tests/bpf-script-example.c

          Note: '--clang-opt' must be placed before '--event/-e'.

	- a group of events surrounded by a pair of brace ("{event1,event2,...}").
	  Each event is separated by commas and the group should be quoted to
	  prevent the shell interpretation.  You also need to use --group on
@@ -547,14 +533,6 @@ PERF_RECORD_SWITCH_CPU_WIDE. In some cases (e.g. Intel PT, CoreSight or Arm SPE)
switch events will be enabled automatically, which can be suppressed by
by the option --no-switch-events.

--clang-path=PATH::
Path to clang binary to use for compiling BPF scriptlets.
(enabled when BPF support is on)

--clang-opt=OPTIONS::
Options passed to clang when compiling BPF scriptlets.
(enabled when BPF support is on)

--vmlinux=PATH::
Specify vmlinux path which has debuginfo.
(enabled when BPF prologue is on)
+0 −12
Original line number Diff line number Diff line
@@ -589,18 +589,6 @@ ifndef NO_LIBELF
	LIBBPF_STATIC := 1
      endif
    endif

    ifndef NO_DWARF
      ifdef PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
        CFLAGS += -DHAVE_BPF_PROLOGUE
        $(call detected,CONFIG_BPF_PROLOGUE)
      else
        msg := $(warning BPF prologue is not supported by architecture $(SRCARCH), missing regs_query_register_offset());
      endif
    else
      msg := $(warning DWARF support is off, BPF prologue is disabled);
    endif

  endif # NO_LIBBPF
endif # NO_LIBELF

+0 −45
Original line number Diff line number Diff line
@@ -37,8 +37,6 @@
#include "util/parse-branch-options.h"
#include "util/parse-regs-options.h"
#include "util/perf_api_probe.h"
#include "util/llvm-utils.h"
#include "util/bpf-loader.h"
#include "util/trigger.h"
#include "util/perf-hooks.h"
#include "util/cpu-set-sched.h"
@@ -2465,16 +2463,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
		}
	}

	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_free_threads;
	}

	/*
	 * Normally perf_session__new would do this, but it doesn't have the
	 * evlist.
@@ -3486,10 +3474,6 @@ static struct option __record_options[] = {
		    "collect kernel callchains"),
	OPT_BOOLEAN(0, "user-callchains", &record.opts.user_callchains,
		    "collect user callchains"),
	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
		   "clang binary to use for compiling BPF scriptlets"),
	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
		   "options passed to clang when compiling BPF scriptlets"),
	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
		   "file", "vmlinux pathname"),
	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
@@ -3967,27 +3951,6 @@ int cmd_record(int argc, const char **argv)

	setlocale(LC_ALL, "");

#ifndef HAVE_LIBBPF_SUPPORT
# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
	set_nobuild('\0', "clang-path", true);
	set_nobuild('\0', "clang-opt", true);
# undef set_nobuild
#endif

#ifndef HAVE_BPF_PROLOGUE
# if !defined (HAVE_DWARF_SUPPORT)
#  define REASON  "NO_DWARF=1"
# elif !defined (HAVE_LIBBPF_SUPPORT)
#  define REASON  "NO_LIBBPF=1"
# else
#  define REASON  "this architecture doesn't support BPF prologue"
# endif
# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
	set_nobuild('\0', "vmlinux", true);
# undef set_nobuild
# undef REASON
#endif

#ifndef HAVE_BPF_SKEL
# define set_nobuild(s, l, m, c) set_option_nobuild(record_options, s, l, m, c)
	set_nobuild('\0', "off-cpu", "no BUILD_BPF_SKEL=1", true);
@@ -4116,14 +4079,6 @@ int cmd_record(int argc, const char **argv)
	if (dry_run)
		goto out;

	err = bpf__setup_stdout(rec->evlist);
	if (err) {
		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
		pr_err("ERROR: Setup BPF stdout failed: %s\n",
			 errbuf);
		goto out;
	}

	err = -ENOMEM;

	if (rec->no_buildid_cache || rec->no_buildid) {
+1 −145
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <api/fs/tracing_path.h>
#ifdef HAVE_LIBBPF_SUPPORT
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#endif
#include "util/bpf_map.h"
#include "util/rlimit.h"
@@ -53,7 +54,6 @@
#include "trace/beauty/beauty.h"
#include "trace-event.h"
#include "util/parse-events.h"
#include "util/bpf-loader.h"
#include "util/tracepoint.h"
#include "callchain.h"
#include "print_binary.h"
@@ -3287,17 +3287,6 @@ static struct bpf_map *trace__find_bpf_map_by_name(struct trace *trace, const ch
	return bpf_object__find_map_by_name(trace->bpf_obj, name);
}

static void trace__set_bpf_map_filtered_pids(struct trace *trace)
{
	trace->filter_pids.map = trace__find_bpf_map_by_name(trace, "pids_filtered");
}

static void trace__set_bpf_map_syscalls(struct trace *trace)
{
	trace->syscalls.prog_array.sys_enter = trace__find_bpf_map_by_name(trace, "syscalls_sys_enter");
	trace->syscalls.prog_array.sys_exit  = trace__find_bpf_map_by_name(trace, "syscalls_sys_exit");
}

static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace, const char *name)
{
	struct bpf_program *pos, *prog = NULL;
@@ -3553,25 +3542,6 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
	return err;
}

static void trace__delete_augmented_syscalls(struct trace *trace)
{
	struct evsel *evsel, *tmp;

	evlist__remove(trace->evlist, trace->syscalls.events.augmented);
	evsel__delete(trace->syscalls.events.augmented);
	trace->syscalls.events.augmented = NULL;

	evlist__for_each_entry_safe(trace->evlist, tmp, evsel) {
		if (evsel->bpf_obj == trace->bpf_obj) {
			evlist__remove(trace->evlist, evsel);
			evsel__delete(evsel);
		}

	}

	bpf_object__close(trace->bpf_obj);
	trace->bpf_obj = NULL;
}
#else // HAVE_LIBBPF_SUPPORT
static struct bpf_map *trace__find_bpf_map_by_name(struct trace *trace __maybe_unused,
						   const char *name __maybe_unused)
@@ -3579,45 +3549,12 @@ static struct bpf_map *trace__find_bpf_map_by_name(struct trace *trace __maybe_u
	return NULL;
}

static void trace__set_bpf_map_filtered_pids(struct trace *trace __maybe_unused)
{
}

static void trace__set_bpf_map_syscalls(struct trace *trace __maybe_unused)
{
}

static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace __maybe_unused,
							    const char *name __maybe_unused)
{
	return NULL;
}

static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace __maybe_unused)
{
	return 0;
}

static void trace__delete_augmented_syscalls(struct trace *trace __maybe_unused)
{
}
#endif // HAVE_LIBBPF_SUPPORT

static bool trace__only_augmented_syscalls_evsels(struct trace *trace)
{
	struct evsel *evsel;

	evlist__for_each_entry(trace->evlist, evsel) {
		if (evsel == trace->syscalls.events.augmented ||
		    evsel->bpf_obj == trace->bpf_obj)
			continue;

		return false;
	}

	return true;
}

static int trace__set_ev_qualifier_filter(struct trace *trace)
{
	if (trace->syscalls.events.sys_enter)
@@ -3981,16 +3918,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
	if (err < 0)
		goto out_error_open;

	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_error_open;
	}

	err = trace__set_filter_pids(trace);
	if (err < 0)
		goto out_error_mem;
@@ -4922,77 +4849,6 @@ int cmd_trace(int argc, const char **argv)
				       "cgroup monitoring only available in system-wide mode");
	}

	evsel = bpf__setup_output_event(trace.evlist, "__augmented_syscalls__");
	if (IS_ERR(evsel)) {
		bpf__strerror_setup_output_event(trace.evlist, PTR_ERR(evsel), bf, sizeof(bf));
		pr_err("ERROR: Setup trace syscalls enter failed: %s\n", bf);
		goto out;
	}

	if (evsel) {
		trace.syscalls.events.augmented = evsel;

		evsel = evlist__find_tracepoint_by_name(trace.evlist, "raw_syscalls:sys_enter");
		if (evsel == NULL) {
			pr_err("ERROR: raw_syscalls:sys_enter not found in the augmented BPF object\n");
			goto out;
		}

		if (evsel->bpf_obj == NULL) {
			pr_err("ERROR: raw_syscalls:sys_enter not associated to a BPF object\n");
			goto out;
		}

		trace.bpf_obj = evsel->bpf_obj;

		/*
		 * If we have _just_ the augmenter event but don't have a
		 * explicit --syscalls, then assume we want all strace-like
		 * syscalls:
		 */
		if (!trace.trace_syscalls && trace__only_augmented_syscalls_evsels(&trace))
			trace.trace_syscalls = true;
		/*
		 * So, if we have a syscall augmenter, but trace_syscalls, aka
		 * strace-like syscall tracing is not set, then we need to trow
		 * away the augmenter, i.e. all the events that were created
		 * from that BPF object file.
		 *
		 * This is more to fix the current .perfconfig trace.add_events
		 * style of setting up the strace-like eBPF based syscall point
		 * payload augmenter.
		 *
		 * All this complexity will be avoided by adding an alternative
		 * to trace.add_events in the form of
		 * trace.bpf_augmented_syscalls, that will be only parsed if we
		 * need it.
		 *
		 * .perfconfig trace.add_events is still useful if we want, for
		 * instance, have msr_write.msr in some .perfconfig profile based
		 * 'perf trace --config determinism.profile' mode, where for some
		 * particular goal/workload type we want a set of events and
		 * output mode (with timings, etc) instead of having to add
		 * all via the command line.
		 *
		 * Also --config to specify an alternate .perfconfig file needs
		 * to be implemented.
		 */
		if (!trace.trace_syscalls) {
			trace__delete_augmented_syscalls(&trace);
		} else {
			trace__set_bpf_map_filtered_pids(&trace);
			trace__set_bpf_map_syscalls(&trace);
			trace.syscalls.unaugmented_prog = trace__find_bpf_program_by_title(&trace, "!raw_syscalls:unaugmented");
		}
	}

	err = bpf__setup_stdout(trace.evlist);
	if (err) {
		bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
		pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
		goto out;
	}

	err = -1;

	if (map_dump_str) {
Loading