diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 5051d3b..fd56a5b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1113,7 +1113,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)

 	argc = parse_options(argc, argv, record_options, record_usage,
 			    PARSE_OPT_STOP_AT_NON_OPTION);
-	perf_evlist__purge_dummy(rec->evlist);

 	if (!argc && target__none(&rec->opts.target))
 		usage_with_options(record_usage, record_options);
@@ -1178,6 +1177,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 		pr_err("Failed to add events from BPF object(s)\n");
 		goto out_symbol_exit;
 	}
+	/*
+	 * Until now let's purge dummy event. Filter options should
+	 * have been attached to real events by perf_evlist__add_bpf().
+	 */
+	perf_evlist__purge_dummy(rec->evlist);

 	symbol__init(NULL);

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 126aa71..c3bc0a8 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -293,6 +293,12 @@ int bpf__foreach_tev(bpf_prog_iter_callback_t func, void *arg)
 	int err;

 	bpf_object__for_each_safe(obj, tmp) {
+		const char *obj_name;
+
+		obj_name = bpf_object__get_name(obj);
+		if (!obj_name)
+			obj_name = "[unknown]";
+
 		bpf_object__for_each_program(prog, obj) {
 			struct probe_trace_event *tev;
 			struct perf_probe_event *pev;
@@ -316,7 +322,7 @@ int bpf__foreach_tev(bpf_prog_iter_callback_t func, void *arg)
 					return fd;
 				}

-				err = func(tev, fd, arg);
+				err = func(tev, obj_name, fd, arg);
 				if (err) {
 					pr_debug("bpf: call back failed, stop iterate\n");
 					return err;
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 34656f8..323e664 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -6,6 +6,7 @@
 #define __BPF_LOADER_H

 #include <linux/compiler.h>
+#include <linux/perf_event.h>
 #include <string.h>
 #include "probe-event.h"
 #include "debug.h"
@@ -13,6 +14,7 @@
 #define PERF_BPF_PROBE_GROUP "perf_bpf_probe"

 typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
+					const char *obj_name,
 					int fd, void *arg);

 #ifdef HAVE_LIBBPF_SUPPORT
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 3bedf64..21a11c9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -195,7 +195,45 @@ error:
 	return -ENOMEM;
 }

-static int add_bpf_event(struct probe_trace_event *tev, int fd,
+static void
+sync_with_dummy(struct perf_evlist *evlist, const char *obj_name,
+		struct list_head *list)
+{
+	struct perf_evsel *dummy_evsel, *pos;
+	const char *filter;
+	bool found = false;
+	int err;
+
+	evlist__for_each(evlist, dummy_evsel) {
+		if (!perf_evsel__is_dummy(dummy_evsel))
+			continue;
+
+		if (strcmp(dummy_evsel->name, obj_name) == 0) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		pr_debug("Failed to find dummy event of '%s'\n",
+			 obj_name);
+		return;
+	}
+
+	filter = dummy_evsel->filter;
+	if (!filter)
+		return;
+
+	list_for_each_entry(pos, list, node) {
+		err = perf_evsel__set_filter(pos, filter);
+		if (err)
+			pr_debug("Failed to set filter '%s' to evsel %s\n",
+				 filter, pos->name);
+	}
+}
+
+static int add_bpf_event(struct probe_trace_event *tev,
+			 const char *obj_name, int fd,
 			 void *arg)
 {
 	struct perf_evlist *evlist = arg;
@@ -203,8 +241,8 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
 	struct list_head list;
 	int err, idx, entries;

-	pr_debug("add bpf event %s:%s and attach bpf program %d\n",
-			tev->group, tev->event, fd);
+	pr_debug("add bpf event %s:%s and attach bpf program %d (from %s)\n",
+			tev->group, tev->event, fd, obj_name);
 	INIT_LIST_HEAD(&list);
 	idx = evlist->nr_entries;

@@ -226,6 +264,15 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
 	list_for_each_entry(pos, &list, node)
 		pos->bpf_fd = fd;
 	entries = idx - evlist->nr_entries;
+
+	sync_with_dummy(evlist, obj_name, &list);
+
+	/*
+	 * Currectly we don't need to link those new events at the
+	 * same place where dummy node reside because order of
+	 * events in cmdline won't be used after
+	 * 'perf_evlist__add_bpf'.
+	 */
 	perf_evlist__splice_list_tail(evlist, &list, entries);
 	return 0;
 }
