linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs
@ 2015-05-27  5:19 Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 01/29] tools: Add __aligned_u64 to types.h Wang Nan
                   ` (28 more replies)
  0 siblings, 29 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This is the 4th version of patch series which tries to introduce eBPF
programs to perf. Based on v4.1-rc3. This patch series improves
'perf record', enables commands like

 # perf record --event bpf-file.o sleep 1

to select events defined in bpf-file.o and filter those events using
bpf programs inside it.

Different from previous (perf tools: introduce 'perf bpf' command to
load eBPF programs.) version, the 4th version drops 'perf bpf'
subcommand, merges event filtering use case directly into 'perf
record'.

Other improvments including:

 1. Simply return an error if byte ordering mismatch, instead of trying
    to correct it.

 2. Introduce zfree() and zclose() to free memory and close file to
    ensure the pointers are set to NULL and fd set to -1.

 3. Use OO style naming. For example, bpf_object__open() instead of
    bpf_open_object() in v3.

 4. libbpf use linked list to link all bpf_object together. Caller
    doesn't need to store pointers of bpf_object and bpf_program.

 5. Doesn't treat 'config' section specially.

 6. Remove 'atexit' hook.

 7. Bugfix: if multiple perf events are created for one kprobe event,
    only the first try to hook eBPF program can success. Other try
    returns EEXIST. Such error should be ignored.

 8. Coding style, makefile and license correction.

Patch 1/29 - 4/29 are preparations, moves some headers from perf
    internal include directory to tools/include. libbpf will use them.

Patch 5/29 - 22/29 introduces libbpf. The design principle is similar
    to v3, except that allow caller iterate over objects using macro.

Patch 23/29 - 29/29 improve 'perf record' subcommand. In patch 24,
    event parsing syntax is improved to accept strings like
    './bpf-file.o' and 'bpf-object.bpf' to be passed by '--event'.

To make it work, following acked patches should be cherry-picked before
applying this series:

 tools: Change FEATURE_TESTS and FEATURE_DISPLAY to weak binding
 perf tools: Set vmlinux_path__nr_entries to 0 in vmlinux_path__exit
 perf/events/core: fix race in bpf program unregister

Wang Nan (29):
  tools: Add __aligned_u64 to types.h
  perf tools: Move linux/kernel.h to tools/include
  perf tools: Move linux/{list.h,poison.h} to tools/include
  bpf tools: Introduce 'bpf' library to tools
  bpf tools: Allow caller to set printing function
  bpf tools: Open eBPF object file and do basic validation
  bpf tools: Check endianess and make libbpf fail early
  bpf tools: Iterate over ELF sections to collect information
  bpf tools: Collect version and license from ELF sections
  bpf tools: Collect map definitions from 'maps' section
  bpf tools: Collect symbol table from SHT_SYMTAB section
  bpf tools: Collect eBPF programs from their own sections
  bpf tools: Collect relocation sections from SHT_REL sections
  bpf tools: Record map accessing instructions for each program
  bpf tools: Add bpf.c/h for common bpf operations
  bpf tools: Create eBPF maps defined in an object file
  bpf tools: Relocate eBPF programs
  bpf tools: Introduce bpf_load_program() to bpf.c
  bpf tools: Load eBPF programs in object files into kernel
  bpf tools: Introduce accessors for struct bpf_program
  bpf tools: Introduce accessors for struct bpf_object
  bpf tools: Link all bpf objects onto a list
  perf tools: Make perf depend on libbpf
  perf record: Enable passing bpf object file to --event
  perf tools: Parse probe points of eBPF programs during preparation
  perf record: Probe at kprobe points
  perf record: Load all eBPF object into kernel
  perf tools: Add bpf_fd field to evsel and config it
  perf tools: Attach eBPF program to perf event

 tools/{perf/util => }/include/linux/kernel.h |   0
 tools/{perf/util => }/include/linux/list.h   |   6 +-
 tools/include/linux/poison.h                 |   1 +
 tools/include/linux/types.h                  |   5 +
 tools/lib/bpf/.gitignore                     |   2 +
 tools/lib/bpf/Build                          |   1 +
 tools/lib/bpf/Makefile                       | 190 ++++++
 tools/lib/bpf/bpf.c                          |  90 +++
 tools/lib/bpf/bpf.h                          |  23 +
 tools/lib/bpf/libbpf.c                       | 969 +++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h                       |  75 +++
 tools/perf/Makefile.perf                     |  19 +-
 tools/perf/builtin-record.c                  |  32 +
 tools/perf/util/Build                        |   1 +
 tools/perf/util/bpf-loader.c                 | 284 ++++++++
 tools/perf/util/bpf-loader.h                 |  32 +
 tools/perf/util/debug.c                      |   5 +
 tools/perf/util/debug.h                      |   1 +
 tools/perf/util/evlist.c                     |  32 +
 tools/perf/util/evlist.h                     |   1 +
 tools/perf/util/evsel.c                      |  17 +
 tools/perf/util/evsel.h                      |   1 +
 tools/perf/util/include/linux/poison.h       |   1 -
 tools/perf/util/parse-events.c               |  16 +
 tools/perf/util/parse-events.h               |   2 +
 tools/perf/util/parse-events.l               |   5 +-
 tools/perf/util/parse-events.y               |  18 +-
 27 files changed, 1822 insertions(+), 7 deletions(-)
 rename tools/{perf/util => }/include/linux/kernel.h (100%)
 rename tools/{perf/util => }/include/linux/list.h (90%)
 create mode 100644 tools/include/linux/poison.h
 create mode 100644 tools/lib/bpf/.gitignore
 create mode 100644 tools/lib/bpf/Build
 create mode 100644 tools/lib/bpf/Makefile
 create mode 100644 tools/lib/bpf/bpf.c
 create mode 100644 tools/lib/bpf/bpf.h
 create mode 100644 tools/lib/bpf/libbpf.c
 create mode 100644 tools/lib/bpf/libbpf.h
 create mode 100644 tools/perf/util/bpf-loader.c
 create mode 100644 tools/perf/util/bpf-loader.h
 delete mode 100644 tools/perf/util/include/linux/poison.h

-- 
1.8.3.4


^ permalink raw reply	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 01/29] tools: Add __aligned_u64 to types.h
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27 13:00   ` Arnaldo Carvalho de Melo
  2015-05-27  5:19 ` [RFC PATCH v4 02/29] perf tools: Move linux/kernel.h to tools/include Wang Nan
                   ` (27 subsequent siblings)
  28 siblings, 1 reply; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

Following patches will introduce linux/bpf.h to a new libbpf library,
which requires definition of __aligned_u64. This patch add it to the
common types.h for tools.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/include/linux/types.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h
index b5cf25e..10a2cdc 100644
--- a/tools/include/linux/types.h
+++ b/tools/include/linux/types.h
@@ -60,6 +60,11 @@ typedef __u32 __bitwise __be32;
 typedef __u64 __bitwise __le64;
 typedef __u64 __bitwise __be64;
 
+/* Taken from uapi/linux/types.h. Required by linux/bpf.h */
+#ifndef __aligned_u64
+# define __aligned_u64 __u64 __attribute__((aligned(8)))
+#endif
+
 struct list_head {
 	struct list_head *next, *prev;
 };
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 02/29] perf tools: Move linux/kernel.h to tools/include
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 01/29] tools: Add __aligned_u64 to types.h Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27 13:03   ` Arnaldo Carvalho de Melo
  2015-05-27  5:19 ` [RFC PATCH v4 03/29] perf tools: Move linux/{list.h,poison.h} " Wang Nan
                   ` (26 subsequent siblings)
  28 siblings, 1 reply; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch moves kernel.h from tools/perf/util/include/linux/kernel.h
to tools/include/linux/kernel.h to enable other libraries use macros in
it, like libbpf which will be introduced by further patches.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/{perf/util => }/include/linux/kernel.h | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename tools/{perf/util => }/include/linux/kernel.h (100%)

diff --git a/tools/perf/util/include/linux/kernel.h b/tools/include/linux/kernel.h
similarity index 100%
rename from tools/perf/util/include/linux/kernel.h
rename to tools/include/linux/kernel.h
-- 
1.8.3.4


^ permalink raw reply	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 03/29] perf tools: Move linux/{list.h,poison.h} to tools/include
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 01/29] tools: Add __aligned_u64 to types.h Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 02/29] perf tools: Move linux/kernel.h to tools/include Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27 13:15   ` Arnaldo Carvalho de Melo
  2015-05-27  5:19 ` [RFC PATCH v4 04/29] bpf tools: Introduce 'bpf' library to tools Wang Nan
                   ` (25 subsequent siblings)
  28 siblings, 1 reply; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch moves list.h from tools/perf/util/include/linux/list.h
to tools/include/linux/list.h to enable other libraries use macros in
it, like libbpf which will be introduced by further patches. Since
list.h depend on poison.h, poison.h is also moved.

Both file use relative path, so one '..' is removed for each header
to make them suit for new directory.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/{perf/util => }/include/linux/list.h | 6 +++---
 tools/include/linux/poison.h               | 1 +
 tools/perf/util/include/linux/poison.h     | 1 -
 3 files changed, 4 insertions(+), 4 deletions(-)
 rename tools/{perf/util => }/include/linux/list.h (90%)
 create mode 100644 tools/include/linux/poison.h
 delete mode 100644 tools/perf/util/include/linux/poison.h

diff --git a/tools/perf/util/include/linux/list.h b/tools/include/linux/list.h
similarity index 90%
rename from tools/perf/util/include/linux/list.h
rename to tools/include/linux/list.h
index 76ddbc7..76b014c 100644
--- a/tools/perf/util/include/linux/list.h
+++ b/tools/include/linux/list.h
@@ -1,10 +1,10 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 
-#include "../../../../include/linux/list.h"
+#include "../../../include/linux/list.h"
 
-#ifndef PERF_LIST_H
-#define PERF_LIST_H
+#ifndef TOOLS_LIST_H
+#define TOOLS_LIST_H
 /**
  * list_del_range - deletes range of entries from list.
  * @begin: first element in the range to delete from the list.
diff --git a/tools/include/linux/poison.h b/tools/include/linux/poison.h
new file mode 100644
index 0000000..0c27bdf
--- /dev/null
+++ b/tools/include/linux/poison.h
@@ -0,0 +1 @@
+#include "../../../include/linux/poison.h"
diff --git a/tools/perf/util/include/linux/poison.h b/tools/perf/util/include/linux/poison.h
deleted file mode 100644
index fef6dbc..0000000
--- a/tools/perf/util/include/linux/poison.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "../../../../include/linux/poison.h"
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 04/29] bpf tools: Introduce 'bpf' library to tools
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (2 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 03/29] perf tools: Move linux/{list.h,poison.h} " Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 05/29] bpf tools: Allow caller to set printing function Wang Nan
                   ` (24 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This is the first patch of libbpf. The goal of libbpf is to create a
standard way for accessing eBPF object files. This patch creates
Makefile and Build for it, allows 'make' to build libbpf.a and
libbpf.so, 'make install' to put them into proper directories.
Most part of Makefile is borrowed from traceevent. Before building,
it checks the existance of libelf in Makefile, and deny to build if
not found. Instead of throwing an error if libelf not found, the error
raises in a phony target "elfdep". This design is to ensure
'make clean' still workable even if libelf is not found.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/.gitignore |   2 +
 tools/lib/bpf/Build      |   1 +
 tools/lib/bpf/Makefile   | 190 +++++++++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.c   |  14 ++++
 tools/lib/bpf/libbpf.h   |  11 +++
 5 files changed, 218 insertions(+)
 create mode 100644 tools/lib/bpf/.gitignore
 create mode 100644 tools/lib/bpf/Build
 create mode 100644 tools/lib/bpf/Makefile
 create mode 100644 tools/lib/bpf/libbpf.c
 create mode 100644 tools/lib/bpf/libbpf.h

diff --git a/tools/lib/bpf/.gitignore b/tools/lib/bpf/.gitignore
new file mode 100644
index 0000000..812aeed
--- /dev/null
+++ b/tools/lib/bpf/.gitignore
@@ -0,0 +1,2 @@
+libbpf_version.h
+FEATURE-DUMP
diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build
new file mode 100644
index 0000000..a316484
--- /dev/null
+++ b/tools/lib/bpf/Build
@@ -0,0 +1 @@
+libbpf-y := libbpf.o
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
new file mode 100644
index 0000000..0715aaa
--- /dev/null
+++ b/tools/lib/bpf/Makefile
@@ -0,0 +1,190 @@
+# Most of this file is copied from tools/lib/traceevent/Makefile
+
+BPF_VERSION = 0
+BPF_PATCHLEVEL = 0
+BPF_EXTRAVERSION = 1
+
+MAKEFLAGS += --no-print-directory
+
+
+# Makefiles suck: This macro sets a default value of $(2) for the
+# variable named by $(1), unless the variable has been set by
+# environment or command line. This is necessary for CC and AR
+# because make sets default values, so the simpler ?= approach
+# won't work as expected.
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+
+INSTALL = install
+
+# Use DESTDIR for installing into a different root directory.
+# This is useful for building a package. The program will be
+# installed in this directory as if it was the root directory.
+# Then the build tool can move it later.
+DESTDIR ?=
+DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
+
+LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
+ifeq ($(LP64), 1)
+  libdir_relative = lib64
+else
+  libdir_relative = lib
+endif
+
+prefix ?= /usr/local
+libdir = $(prefix)/$(libdir_relative)
+man_dir = $(prefix)/share/man
+man_dir_SQ = '$(subst ','\'',$(man_dir))'
+
+export man_dir man_dir_SQ INSTALL
+export DESTDIR DESTDIR_SQ
+
+include ../../scripts/Makefile.include
+
+# copy a bit from Linux kbuild
+
+ifeq ("$(origin V)", "command line")
+  VERBOSE = $(V)
+endif
+ifndef VERBOSE
+  VERBOSE = 0
+endif
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+FEATURE_DISPLAY = libelf libelf-getphdrnum libelf-mmap
+FEATURE_TESTS = libelf
+include $(srctree)/tools/build/Makefile.feature
+
+export prefix libdir src obj
+
+# Shell quotes
+libdir_SQ = $(subst ','\'',$(libdir))
+libdir_relative_SQ = $(subst ','\'',$(libdir_relative))
+plugin_dir_SQ = $(subst ','\'',$(plugin_dir))
+
+LIB_FILE = libbpf.a libbpf.so
+
+VERSION		= $(BPF_VERSION)
+PATCHLEVEL	= $(BPF_PATCHLEVEL)
+EXTRAVERSION	= $(BPF_EXTRAVERSION)
+
+OBJ		= $@
+N		=
+
+LIBBPF_VERSION = $(BPF_VERSION).$(BPF_PATCHLEVEL).$(BPF_EXTRAVERSION)
+
+INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi
+
+# Set compile option CFLAGS
+ifdef EXTRA_CFLAGS
+  CFLAGS := $(EXTRA_CFLAGS)
+else
+  CFLAGS := -g -Wall
+endif
+
+ifeq ($(feature-libelf-mmap), 1)
+  override CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
+endif
+
+ifeq ($(feature-libelf-getphdrnum), 1)
+  override CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
+endif
+
+# Append required CFLAGS
+override CFLAGS += $(EXTRA_WARNINGS)
+override CFLAGS += -Werror -Wall
+override CFLAGS += -fPIC
+override CFLAGS += $(INCLUDES)
+
+ifeq ($(VERBOSE),1)
+  Q =
+else
+  Q = @
+endif
+
+# Disable command line variables (CFLAGS) overide from top
+# level Makefile (perf), otherwise build Makefile will get
+# the same command line setup.
+MAKEOVERRIDES=
+
+export srctree OUTPUT CC LD CFLAGS V
+build := -f $(srctree)/tools/build/Makefile.build dir=. obj
+
+BPF_IN    := $(OUTPUT)libbpf-in.o
+LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
+
+CMD_TARGETS = $(LIB_FILE)
+
+TARGETS = $(CMD_TARGETS)
+
+all: $(VERSION_FILES) all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+$(BPF_IN): force elfdep
+	$(Q)$(MAKE) $(build)=libbpf
+
+$(OUTPUT)libbpf.so: $(BPF_IN)
+	$(QUIET_LINK)$(CC) --shared $^ -o $@
+
+$(OUTPUT)libbpf.a: $(BPF_IN)
+	$(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
+
+define update_dir
+  (echo $1 > $@.tmp;				\
+   if [ -r $@ ] && cmp -s $@ $@.tmp; then	\
+     rm -f $@.tmp;				\
+   else						\
+     echo '  UPDATE                 $@';	\
+     mv -f $@.tmp $@;				\
+   fi);
+endef
+
+define do_install
+	if [ ! -d '$(DESTDIR_SQ)$2' ]; then		\
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2';	\
+	fi;						\
+	$(INSTALL) $1 '$(DESTDIR_SQ)$2'
+endef
+
+install_lib: all_cmd
+	$(call QUIET_INSTALL, $(LIB_FILE)) \
+		$(call do_install,$(LIB_FILE),$(libdir_SQ))
+
+install: install_lib
+
+### Cleaning rules
+
+config-clean:
+	$(call QUIET_CLEAN, config)
+	$(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null
+
+clean:
+	$(call QUIET_CLEAN, libbpf) $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \
+		$(RM) LIBBPF-CFLAGS
+	$(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP
+	
+
+
+PHONY += force elfdep
+force:
+
+elfdep:
+	@if [ "$(feature-libelf)" != "1" ]; then echo "No libelf found"; exit -1 ; fi
+
+# Declare the contents of the .PHONY variable as phony.  We keep that
+# information in a variable so we can use it in if_changed and friends.
+.PHONY: $(PHONY)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
new file mode 100644
index 0000000..c08d6bc
--- /dev/null
+++ b/tools/lib/bpf/libbpf.c
@@ -0,0 +1,14 @@
+/*
+ * Common eBPF ELF object loading operations.
+ *
+ * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
+ * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2015 Huawei Inc.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <asm/unistd.h>
+#include <linux/bpf.h>
+
+#include "libbpf.h"
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
new file mode 100644
index 0000000..a6f46d9
--- /dev/null
+++ b/tools/lib/bpf/libbpf.h
@@ -0,0 +1,11 @@
+/*
+ * Common eBPF ELF object loading operations.
+ *
+ * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
+ * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2015 Huawei Inc.
+ */
+#ifndef __BPF_LIBBPF_H
+#define __BPF_LIBBPF_H
+
+#endif
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 05/29] bpf tools: Allow caller to set printing function
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (3 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 04/29] bpf tools: Introduce 'bpf' library to tools Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-29 13:35   ` Namhyung Kim
  2015-05-27  5:19 ` [RFC PATCH v4 06/29] bpf tools: Open eBPF object file and do basic validation Wang Nan
                   ` (23 subsequent siblings)
  28 siblings, 1 reply; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

By libbpf_set_print(), users of libbpf are allowed to register he/she
own debug, info and warning printing functions. Libbpf will use those
functions to print messages. If not provided, default info and warning
printing functions are fprintf(stderr, ...); defailt debug printing
is NULL.

This API is designed to be used by perf, enables it to register its own
logging functions to make all logs uniform, instead of separated
logging level control.

Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h |  4 ++++
 2 files changed, 47 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index c08d6bc..49091c3 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -7,8 +7,51 @@
  */
 
 #include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
 #include <unistd.h>
 #include <asm/unistd.h>
 #include <linux/bpf.h>
 
 #include "libbpf.h"
+
+#define __printf(a, b)	__attribute__((format(printf, a, b)))
+
+__printf(1, 2)
+static int __base_pr(const char *format, ...)
+{
+	va_list args;
+	int err;
+
+	va_start(args, format);
+	err = vfprintf(stderr, format, args);
+	va_end(args);
+	return err;
+}
+
+static __printf(1, 2) int (*__pr_warning)(const char *format, ...) =
+	__base_pr;
+static __printf(1, 2) int (*__pr_info)(const char *format, ...) =
+	__base_pr;
+static __printf(1, 2) int (*__pr_debug)(const char *format, ...) =
+	NULL;
+
+#define __pr(func, fmt, ...)	\
+do { 				\
+	if ((func))	\
+		(func)("libbpf: " fmt, ##__VA_ARGS__); \
+} while(0)
+
+#define pr_warning(fmt, ...)	__pr(__pr_warning, fmt, ##__VA_ARGS__)
+#define pr_info(fmt, ...)	__pr(__pr_info, fmt, ##__VA_ARGS__)
+#define pr_debug(fmt, ...)	__pr(__pr_debug, fmt, ##__VA_ARGS__)
+
+void libbpf_set_print(int (*warn)(const char *format, ...),
+		      int (*info)(const char *format, ...),
+		      int (*debug)(const char *format, ...))
+{
+	__pr_warning = warn;
+	__pr_info = info;
+	__pr_debug = debug;
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index a6f46d9..430b122 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -8,4 +8,8 @@
 #ifndef __BPF_LIBBPF_H
 #define __BPF_LIBBPF_H
 
+void libbpf_set_print(int (*warn)(const char *format, ...),
+		      int (*info)(const char *format, ...),
+		      int (*debug)(const char *format, ...));
+
 #endif
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 06/29] bpf tools: Open eBPF object file and do basic validation
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (4 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 05/29] bpf tools: Allow caller to set printing function Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-28  1:44   ` Alexei Starovoitov
  2015-05-27  5:19 ` [RFC PATCH v4 07/29] bpf tools: Check endianess and make libbpf fail early Wang Nan
                   ` (22 subsequent siblings)
  28 siblings, 1 reply; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch defines basic interface of libbpf. 'struct bpf_object' will
be the handler of each object file. Its internal structure is hide to
user. eBPF object files are compiled by LLVM as ELF format. In this
patch, libelf is used to open those files, read EHDR and do basic
validation according to e_type and e_machine.

All elf related staffs are grouped together and reside in efile field of
'struct bpf_object'. bpf_object__elf_finish() is introduced to clear it.

After all eBPF programs in an object file are loaded, related ELF
information is useless. Close the object file and free those memory.

zfree() and zclose() are introduced to ensure setting NULL pointers and
negative file descriptors after resources are released.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h |   8 +++
 2 files changed, 160 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 49091c3..e910fb8 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -11,8 +11,12 @@
 #include <stdarg.h>
 #include <string.h>
 #include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
 #include <asm/unistd.h>
 #include <linux/bpf.h>
+#include <libelf.h>
+#include <gelf.h>
 
 #include "libbpf.h"
 
@@ -55,3 +59,151 @@ void libbpf_set_print(int (*warn)(const char *format, ...),
 	__pr_info = info;
 	__pr_debug = debug;
 }
+
+/* Copied from tools/perf/util/util.h */
+#ifndef zfree
+# define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
+#endif
+
+#ifndef zclose
+# define zclose(fd) ({			\
+	int ___err = 0;			\
+	if ((fd) >= 0)			\
+		___err = close((fd));	\
+	fd = -1;			\
+	___err;})
+#endif
+
+#ifdef HAVE_LIBELF_MMAP_SUPPORT
+# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ_MMAP
+#else
+# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
+#endif
+
+struct bpf_object {
+	/*
+	 * Information when doing elf related work. Only valid if fd
+	 * is valid.
+	 */
+	struct {
+		int fd;
+		Elf *elf;
+		GElf_Ehdr ehdr;
+	} efile;
+	char path[];
+};
+#define obj_elf_valid(o)	((o)->efile.fd >= 0)
+
+static struct bpf_object *bpf_object__new(const char *path)
+{
+	struct bpf_object *obj;
+
+	obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1);
+	if (!obj) {
+		pr_warning("alloc memory failed for %s\n", path);
+		return NULL;
+	}
+
+	strcpy(obj->path, path);
+	obj->efile.fd = -1;
+	return obj;
+}
+
+static void bpf_object__elf_finish(struct bpf_object *obj)
+{
+	if (!obj_elf_valid(obj))
+		return;
+
+	if (obj->efile.elf) {
+		elf_end(obj->efile.elf);
+		obj->efile.elf = NULL;
+	}
+	zclose(obj->efile.fd);
+}
+
+static int bpf_object__elf_init(struct bpf_object *obj)
+{
+	int err = 0;
+	GElf_Ehdr *ep;
+
+	if (obj_elf_valid(obj)) {
+		pr_warning("elf init: internal error\n");
+		return -EEXIST;
+	}
+	
+	obj->efile.fd = open(obj->path, O_RDONLY);
+	if (obj->efile.fd < 0) {
+		pr_warning("failed to open %s: %s\n", obj->path,
+				strerror(errno));
+		return -errno;
+	}
+
+	obj->efile.elf = elf_begin(obj->efile.fd,
+				 LIBBPF_ELF_C_READ_MMAP,
+				 NULL);
+	if (!obj->efile.elf) {
+		pr_warning("failed to open %s as ELF file\n",
+				obj->path);
+		err = -EINVAL;
+		goto errout;
+	}
+
+	if (!gelf_getehdr(obj->efile.elf, &obj->efile.ehdr)) {
+		pr_warning("failed to get EHDR from %s\n",
+				obj->path);
+		err = -EINVAL;
+		goto errout;
+	}
+	ep = &obj->efile.ehdr;
+
+	if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) {
+		pr_warning("%s is not an eBPF object file\n",
+			obj->path);
+		err = -EINVAL;
+		goto errout;
+	}
+
+	return 0;
+errout:
+	bpf_object__elf_finish(obj);
+	return err;
+}
+
+struct bpf_object *bpf_object__open(const char *path)
+{
+	struct bpf_object *obj;
+
+	/* param validation */
+	if (!path)
+		return NULL;
+
+ 	pr_debug("loading %s\n", path);
+
+	if (elf_version(EV_CURRENT) == EV_NONE) {
+		pr_warning("failed to init libelf for %s\n", path);
+		return NULL;
+	}
+
+	obj = bpf_object__new(path);
+	if (!obj)
+		return NULL;
+
+	if (bpf_object__elf_init(obj))
+		goto out;
+
+	bpf_object__elf_finish(obj);
+	return obj;
+out:
+	bpf_object__close(obj);
+	return NULL;
+}
+
+void bpf_object__close(struct bpf_object *obj)
+{
+	if (!obj)
+		return;
+
+	bpf_object__elf_finish(obj);
+
+	free(obj);
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 430b122..88d62de 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -8,8 +8,16 @@
 #ifndef __BPF_LIBBPF_H
 #define __BPF_LIBBPF_H
 
+#include <stdio.h>
+
 void libbpf_set_print(int (*warn)(const char *format, ...),
 		      int (*info)(const char *format, ...),
 		      int (*debug)(const char *format, ...));
 
+/* Hide internal to user */
+struct bpf_object;
+
+struct bpf_object *bpf_object__open(const char *path);
+void bpf_object__close(struct bpf_object *object);
+
 #endif
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 07/29] bpf tools: Check endianess and make libbpf fail early
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (5 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 06/29] bpf tools: Open eBPF object file and do basic validation Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-28  1:45   ` Alexei Starovoitov
  2015-05-27  5:19 ` [RFC PATCH v4 08/29] bpf tools: Iterate over ELF sections to collect information Wang Nan
                   ` (21 subsequent siblings)
  28 siblings, 1 reply; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

Check endianess according to EHDR. Code is taken from
tools/perf/util/symbol-elf.c.

Libbpf doesn't magically convert missmatched endianess. See discussion
on https://lkml.org/lkml/2015/5/18/650 that, even if we swap
eBPF instructions to correct byte order, we are unable to deal with
endianess in code logical generated by LLVM.

Therefore, libbpf should simply reject missmatched ELF object, and let
LLVM to create good code.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e910fb8..dbbea0c 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -169,6 +169,34 @@ errout:
 	return err;
 }
 
+static int
+bpf_object__check_endianess(struct bpf_object *obj)
+{
+	static unsigned int const endian = 1;
+
+	switch (obj->efile.ehdr.e_ident[EI_DATA]) {
+	case ELFDATA2LSB:
+		/* We are big endian, BPF obj is little endian. */
+		if (*(unsigned char const *)&endian != 1)
+			goto mismatch;
+		break;
+
+	case ELFDATA2MSB:
+		/* We are little endian, BPF obj is big endian. */
+		if (*(unsigned char const *)&endian != 0)
+			goto mismatch;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+
+mismatch:
+	pr_warning("Error: endianess mismatch.\n");
+	return -EINVAL;
+}
+
 struct bpf_object *bpf_object__open(const char *path)
 {
 	struct bpf_object *obj;
@@ -190,6 +218,8 @@ struct bpf_object *bpf_object__open(const char *path)
 
 	if (bpf_object__elf_init(obj))
 		goto out;
+	if (bpf_object__check_endianess(obj))
+		goto out;
 
 	bpf_object__elf_finish(obj);
 	return obj;
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 08/29] bpf tools: Iterate over ELF sections to collect information
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (6 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 07/29] bpf tools: Check endianess and make libbpf fail early Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-28  1:46   ` Alexei Starovoitov
  2015-05-27  5:19 ` [RFC PATCH v4 09/29] bpf tools: Collect version and license from ELF sections Wang Nan
                   ` (20 subsequent siblings)
  28 siblings, 1 reply; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

bpf_obj_elf_collect() is introduced to iterate over each elf sections
to collection informations in eBPF object files. This function will
futher enhanced to collect license, kernel version, programs, configs
and map information.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index dbbea0c..16e47a3 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -197,6 +197,57 @@ mismatch:
 	return -EINVAL;
 }
 
+static int bpf_object__elf_collect(struct bpf_object *obj)
+{
+	Elf *elf = obj->efile.elf;
+	GElf_Ehdr *ep = &obj->efile.ehdr;
+	Elf_Scn *scn = NULL;
+	int idx = 0, err = 0;
+
+	/* Elf is corrupted/truncated, avoid calling elf_strptr. */
+	if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
+		pr_warning("failed to get e_shstrndx from %s\n",
+			   obj->path);
+		return -EINVAL;
+	}
+
+	while ((scn = elf_nextscn(elf, scn)) != NULL) {
+		char *name;
+		GElf_Shdr sh;
+		Elf_Data *data;
+
+		idx++;
+		if (gelf_getshdr(scn, &sh) != &sh) {
+			pr_warning("failed to get section header from %s\n",
+				   obj->path);
+			err = -EINVAL;
+			goto out;
+		}
+
+		name = elf_strptr(elf, ep->e_shstrndx, sh.sh_name);
+		if (!name) {
+			pr_warning("failed to get section name from %s\n",
+				   obj->path);
+			err = -EINVAL;
+			goto out;
+		}
+
+		data = elf_getdata(scn, 0);
+		if (!data) {
+			pr_warning("failed to get section data from %s(%s)\n",
+				   name, obj->path);
+			err = -EINVAL;
+			goto out;
+		}
+		pr_debug("section %s, size %ld, link %d, flags %lx, type=%d\n",
+			 name, (unsigned long)data->d_size,
+			 (int)sh.sh_link, (unsigned long)sh.sh_flags,
+			 (int)sh.sh_type);
+	}
+out:
+	return err;
+}
+
 struct bpf_object *bpf_object__open(const char *path)
 {
 	struct bpf_object *obj;
@@ -220,6 +271,8 @@ struct bpf_object *bpf_object__open(const char *path)
 		goto out;
 	if (bpf_object__check_endianess(obj))
 		goto out;
+	if (bpf_object__elf_collect(obj))
+		goto out;
 
 	bpf_object__elf_finish(obj);
 	return obj;
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 09/29] bpf tools: Collect version and license from ELF sections
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (7 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 08/29] bpf tools: Iterate over ELF sections to collect information Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-28  1:48   ` Alexei Starovoitov
  2015-05-27  5:19 ` [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section Wang Nan
                   ` (19 subsequent siblings)
  28 siblings, 1 reply; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

Expand bpf_obj_elf_collect() to collect license and kernel version
information in eBPF object file. eBPF object file should have a section
named 'license', which contains a string. It should also have a section
named 'version', contains a u32 LINUX_VERSION_CODE.

bpf_obj_validate() is introduced to validate object file after loaded.
Currently it only check existance of 'version' section.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 16e47a3..15525ad 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -14,6 +14,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <asm/unistd.h>
+#include <linux/kernel.h>
 #include <linux/bpf.h>
 #include <libelf.h>
 #include <gelf.h>
@@ -81,6 +82,8 @@ void libbpf_set_print(int (*warn)(const char *format, ...),
 #endif
 
 struct bpf_object {
+	char license[64];
+	u32 kern_version;
 	/*
 	 * Information when doing elf related work. Only valid if fd
 	 * is valid.
@@ -197,6 +200,32 @@ mismatch:
 	return -EINVAL;
 }
 
+static int
+bpf_object__init_license(struct bpf_object *obj,
+			 void *data, size_t size)
+{
+	memcpy(obj->license, data,
+	       min(size, sizeof(obj->license) - 1));
+	pr_debug("license of %s is %s\n", obj->path, obj->license);
+	return 0;
+}
+
+static int
+bpf_object__init_kversion(struct bpf_object *obj,
+			  void *data, size_t size)
+{
+	u32 kver;
+	if (size < sizeof(kver)) {
+		pr_warning("invalid kver section in %s\n", obj->path);
+		return -EINVAL;
+	}
+	memcpy(&kver, data, sizeof(kver));
+	obj->kern_version = kver;
+	pr_debug("kernel version of %s is %x\n", obj->path,
+		 obj->kern_version);
+	return 0;
+}
+
 static int bpf_object__elf_collect(struct bpf_object *obj)
 {
 	Elf *elf = obj->efile.elf;
@@ -243,11 +272,32 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 			 name, (unsigned long)data->d_size,
 			 (int)sh.sh_link, (unsigned long)sh.sh_flags,
 			 (int)sh.sh_type);
+
+		if (strcmp(name, "license") == 0)
+			err = bpf_object__init_license(obj,
+						       data->d_buf,
+						       data->d_size);
+		else if (strcmp(name, "version") == 0)
+			err = bpf_object__init_kversion(obj,
+							data->d_buf,
+							data->d_size);
+		if (err)
+			goto out;
 	}
 out:
 	return err;
 }
 
+static int bpf_object__validate(struct bpf_object *obj)
+{
+	if (obj->kern_version == 0) {
+		pr_warning("%s doesn't provide kernel version\n",
+			   obj->path);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 struct bpf_object *bpf_object__open(const char *path)
 {
 	struct bpf_object *obj;
@@ -273,6 +323,8 @@ struct bpf_object *bpf_object__open(const char *path)
 		goto out;
 	if (bpf_object__elf_collect(obj))
 		goto out;
+	if (bpf_object__validate(obj))
+		goto out;
 
 	bpf_object__elf_finish(obj);
 	return obj;
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (8 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 09/29] bpf tools: Collect version and license from ELF sections Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-28  1:53   ` Alexei Starovoitov
  2015-05-27  5:19 ` [RFC PATCH v4 11/29] bpf tools: Collect symbol table from SHT_SYMTAB section Wang Nan
                   ` (18 subsequent siblings)
  28 siblings, 1 reply; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

If maps are used by eBPF programs, corresponding object file(s) should
contain a section named 'map'. Which contains map definitions. This
patch copies the data of the whole section. Map data parsing should be
acted just before map loading.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 15525ad..da83766 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -84,6 +84,9 @@ void libbpf_set_print(int (*warn)(const char *format, ...),
 struct bpf_object {
 	char license[64];
 	u32 kern_version;
+	void *maps_buf;
+	size_t maps_buf_sz;
+
 	/*
 	 * Information when doing elf related work. Only valid if fd
 	 * is valid.
@@ -226,6 +229,28 @@ bpf_object__init_kversion(struct bpf_object *obj,
 	return 0;
 }
 
+static int
+bpf_object__init_maps(struct bpf_object *obj, void *data,
+		      size_t size)
+{
+	if (size == 0) {
+		pr_debug("%s doesn't need map definition\n",
+			 obj->path);
+		return 0;
+	}
+
+	obj->maps_buf = malloc(size);
+	if (!obj->maps_buf) {
+		pr_warning("malloc maps failed: %s\n", obj->path);
+		return -ENOMEM;
+	}
+
+	obj->maps_buf_sz = size;
+	memcpy(obj->maps_buf, data, size);
+	pr_debug("maps in %s: %ld bytes\n", obj->path, (long)size);
+	return 0;
+}
+
 static int bpf_object__elf_collect(struct bpf_object *obj)
 {
 	Elf *elf = obj->efile.elf;
@@ -281,6 +306,9 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 			err = bpf_object__init_kversion(obj,
 							data->d_buf,
 							data->d_size);
+		else if (strcmp(name, "maps") == 0)
+			err = bpf_object__init_maps(obj, data->d_buf,
+						    data->d_size);
 		if (err)
 			goto out;
 	}
@@ -340,5 +368,6 @@ void bpf_object__close(struct bpf_object *obj)
 
 	bpf_object__elf_finish(obj);
 
+	zfree(&obj->maps_buf);
 	free(obj);
 }
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 11/29] bpf tools: Collect symbol table from SHT_SYMTAB section
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (9 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 12/29] bpf tools: Collect eBPF programs from their own sections Wang Nan
                   ` (17 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch collects symbols section. This section is useful when
linking ELF maps.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index da83766..d89fd42 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -95,6 +95,7 @@ struct bpf_object {
 		int fd;
 		Elf *elf;
 		GElf_Ehdr ehdr;
+		Elf_Data *symbols;
 	} efile;
 	char path[];
 };
@@ -124,6 +125,7 @@ static void bpf_object__elf_finish(struct bpf_object *obj)
 		elf_end(obj->efile.elf);
 		obj->efile.elf = NULL;
 	}
+	obj->efile.symbols = NULL;
 	zclose(obj->efile.fd);
 }
 
@@ -309,6 +311,14 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 		else if (strcmp(name, "maps") == 0)
 			err = bpf_object__init_maps(obj, data->d_buf,
 						    data->d_size);
+		else if (sh.sh_type == SHT_SYMTAB) {
+			if (obj->efile.symbols) {
+				pr_warning("bpf: multiple SYMTAB in %s\n",
+					   obj->path);
+				err = -EEXIST;
+			} else
+				obj->efile.symbols = data;
+		}
 		if (err)
 			goto out;
 	}
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 12/29] bpf tools: Collect eBPF programs from their own sections
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (10 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 11/29] bpf tools: Collect symbol table from SHT_SYMTAB section Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 13/29] bpf tools: Collect relocation sections from SHT_REL sections Wang Nan
                   ` (16 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch collects all programs in an object file into an array of
'struct bpf_program' for further processing. That structure is for
representing each eBPF program. 'bpf_prog' should be a better name, but
it has been used by linux/filter.h. Although it is a kernel space name,
I still prefer to call it 'bpf_program' to prevent possible confusion.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index d89fd42..17b2aa1 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -81,12 +81,27 @@ void libbpf_set_print(int (*warn)(const char *format, ...),
 # define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
 #endif
 
+/* 
+ * bpf_prog should be a better name but it has been used in
+ * linux/filter.h.
+ */
+struct bpf_program {
+	/* Index in elf obj file, for relocation use. */
+	int idx;
+	char *section_name;
+	struct bpf_insn *insns;
+	size_t insns_cnt;
+};
+
 struct bpf_object {
 	char license[64];
 	u32 kern_version;
 	void *maps_buf;
 	size_t maps_buf_sz;
 
+	struct bpf_program *programs;
+	size_t nr_programs;
+
 	/*
 	 * Information when doing elf related work. Only valid if fd
 	 * is valid.
@@ -101,6 +116,74 @@ struct bpf_object {
 };
 #define obj_elf_valid(o)	((o)->efile.fd >= 0)
 
+static void bpf_program__clear(struct bpf_program *prog)
+{
+	if (!prog)
+		return;
+
+	zfree(&prog->section_name);
+	zfree(&prog->insns);
+	prog->insns_cnt = 0;
+	prog->idx = -1;
+}
+
+static struct bpf_program *
+bpf_program__new(struct bpf_object *obj, void *data, size_t size,
+		 char *name, int idx)
+{
+	struct bpf_program *prog, *progs;
+	int nr_progs;
+
+	if (size < sizeof(struct bpf_insn)) {
+		pr_warning("corrupted section '%s'\n", name);
+		return NULL;
+	}
+	
+	progs = obj->programs;
+	nr_progs = obj->nr_programs;
+
+	progs = realloc(progs, sizeof(*prog) * (nr_progs + 1));
+	if (!progs) {
+		/*
+		 * In this case the original obj->programs
+		 * is still valid, so don't need special treat for
+		 * bpf_close_object().
+		 */
+		pr_warning("failed to alloc a new program '%s'\n",
+			   name);
+		return NULL;
+	}
+
+	obj->programs = progs;
+
+	prog = &progs[nr_progs];
+	bzero(prog, sizeof(*prog));
+
+	obj->nr_programs = nr_progs + 1;
+
+	prog->section_name = strdup(name);
+	if (!prog->section_name) {
+		pr_warning("failed to alloc name for prog %s\n",
+			   name);
+		goto out;
+	}
+
+	prog->insns = malloc(size);
+	if (!prog->insns) {
+		pr_warning("failed to alloc insns for %s\n", name);
+		goto out;
+	}
+	prog->insns_cnt = size / sizeof(struct bpf_insn);
+	memcpy(prog->insns, data,
+	       prog->insns_cnt * sizeof(struct bpf_insn));
+	prog->idx = idx;
+
+	return prog;
+out:
+	bpf_program__clear(prog);
+	return NULL;
+}
+
 static struct bpf_object *bpf_object__new(const char *path)
 {
 	struct bpf_object *obj;
@@ -318,6 +401,21 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 				err = -EEXIST;
 			} else
 				obj->efile.symbols = data;
+		} else if ((sh.sh_type == SHT_PROGBITS) &&
+			   (sh.sh_flags & SHF_EXECINSTR) &&
+			   (data->d_size > 0)) {
+			struct bpf_program *prog;
+
+			prog = bpf_program__new(obj, data->d_buf,
+						data->d_size, name,
+						idx);
+			if (!prog) {
+				pr_warning("failed to alloc program %s (%s)",
+					   name, obj->path);
+				err = -ENOMEM;
+			} else
+				pr_debug("found program %s\n",
+					 prog->section_name);
 		}
 		if (err)
 			goto out;
@@ -373,11 +471,18 @@ out:
 
 void bpf_object__close(struct bpf_object *obj)
 {
+	size_t i;
+
 	if (!obj)
 		return;
 
 	bpf_object__elf_finish(obj);
 
 	zfree(&obj->maps_buf);
+
+	for (i = 0; i < obj->nr_programs; i++)
+		bpf_program__clear(&obj->programs[i]);
+	zfree(&obj->programs);
+
 	free(obj);
 }
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 13/29] bpf tools: Collect relocation sections from SHT_REL sections
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (11 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 12/29] bpf tools: Collect eBPF programs from their own sections Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 14/29] bpf tools: Record map accessing instructions for each program Wang Nan
                   ` (15 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch collects relocation sections into 'struct object'.
Such sections are used for connecting maps to bpf programs.
'reloc' field in 'struct bpf_object' is introduced for storing
such informations.

This patch simply store the data into 'reloc' field. Following
patch will parse them to know the exact instructions which are
needed to be relocated.

Note that the collected data will be invalid after ELF object file
is closed.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 17b2aa1..560018e 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -111,6 +111,11 @@ struct bpf_object {
 		Elf *elf;
 		GElf_Ehdr ehdr;
 		Elf_Data *symbols;
+		struct {
+			GElf_Shdr shdr;
+			Elf_Data *data;
+		} *reloc;
+		int nr_reloc;
 	} efile;
 	char path[];
 };
@@ -209,6 +214,9 @@ static void bpf_object__elf_finish(struct bpf_object *obj)
 		obj->efile.elf = NULL;
 	}
 	obj->efile.symbols = NULL;
+
+	zfree(&obj->efile.reloc);
+	obj->efile.nr_reloc = 0;
 	zclose(obj->efile.fd);
 }
 
@@ -416,6 +424,24 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 			} else
 				pr_debug("found program %s\n",
 					 prog->section_name);
+		} else if (sh.sh_type == SHT_REL) {
+			void *reloc = obj->efile.reloc;
+			int nr_reloc = obj->efile.nr_reloc;
+
+			reloc = realloc(reloc,
+					sizeof(*obj->efile.reloc) * (++nr_reloc));
+			if (!reloc) {
+				pr_warning("realloc failed\n");
+				err = -ENOMEM;
+			} else {
+				int n = nr_reloc - 1;
+
+				obj->efile.reloc = reloc;
+				obj->efile.nr_reloc = nr_reloc;
+
+				obj->efile.reloc[n].shdr = sh;
+				obj->efile.reloc[n].data = data;
+			}
 		}
 		if (err)
 			goto out;
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 14/29] bpf tools: Record map accessing instructions for each program
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (12 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 13/29] bpf tools: Collect relocation sections from SHT_REL sections Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 15/29] bpf tools: Add bpf.c/h for common bpf operations Wang Nan
                   ` (14 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch records the indics of instructions which are needed to be
relocated. Those information are saved in 'reloc_desc' field in
'struct bpf_program'. In loading phase (this patch takes effect in
opening phase), the collected instructions will be replaced by
map loading instructions.

Since we are going to close the ELF file and clear all data at the end
of 'opening' phase, ELF information will no longer be valid in
'loading' phase. We have to locate the instructions before maps are
loaded, instead of directly modifying the instruction.

'struct bpf_map_def' is introduce in this patch to let us know how many
maps defined in the object.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h |  13 ++++++
 2 files changed, 137 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 560018e..3a7ff7d 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <inttypes.h>
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -91,6 +92,12 @@ struct bpf_program {
 	char *section_name;
 	struct bpf_insn *insns;
 	size_t insns_cnt;
+
+	struct {
+		int insn_idx;
+		int map_idx;
+	} *reloc_desc;
+	int nr_reloc;
 };
 
 struct bpf_object {
@@ -128,6 +135,9 @@ static void bpf_program__clear(struct bpf_program *prog)
 
 	zfree(&prog->section_name);
 	zfree(&prog->insns);
+	zfree(&prog->reloc_desc);
+
+	prog->nr_reloc = 0;
 	prog->insns_cnt = 0;
 	prog->idx = -1;
 }
@@ -450,6 +460,118 @@ out:
 	return err;
 }
 
+static struct bpf_program *
+bpf_object__find_prog_by_idx(struct bpf_object *obj, int idx)
+{
+	struct bpf_program *prog;
+	size_t i;
+
+	for (i = 0; i < obj->nr_programs; i++) {
+		prog = &obj->programs[i];
+		if (prog->idx == idx)
+			return prog;
+	}
+	return NULL;
+}
+
+static int
+bpf_program__collect_reloc(struct bpf_program *prog,
+			   size_t nr_maps, GElf_Shdr *shdr,
+			   Elf_Data *data, Elf_Data *symbols)
+{
+	int i, nrels;
+
+	pr_debug("collecting relocating info for: '%s'\n",
+		 prog->section_name);
+	nrels = shdr->sh_size / shdr->sh_entsize;
+	
+	prog->reloc_desc = malloc(sizeof(*prog->reloc_desc) * nrels);
+	if (!prog->reloc_desc) {
+		pr_warning("failed to alloc memory in relocation\n");
+		return -ENOMEM;
+	}
+	prog->nr_reloc = nrels;
+
+	for (i = 0; i < nrels; i++) {
+		GElf_Sym sym;
+		GElf_Rel rel;
+		unsigned int insn_idx;
+		struct bpf_insn *insns = prog->insns;
+		size_t map_idx;
+
+		if (!gelf_getrel(data, i, &rel)) {
+			pr_warning("relocation: failed to get %d reloc\n", i);
+			return -EINVAL;
+		}
+
+		insn_idx = rel.r_offset / sizeof(struct bpf_insn);
+		pr_debug("relocation: insn_idx=%u\n", insn_idx);
+
+		if (!gelf_getsym(symbols,
+				 GELF_R_SYM(rel.r_info),
+				 &sym)) {
+			pr_warning("relocation: symbol %"PRIx64" not found\n",
+				   GELF_R_SYM(rel.r_info));
+			return -EINVAL;
+		}
+
+		if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) {
+			pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n",
+				   insn_idx, insns[insn_idx].code);
+			return -EINVAL;
+		}
+
+		map_idx = sym.st_value / sizeof(struct bpf_map_def);
+		if (map_idx >= nr_maps) {
+			pr_warning("bpf relocation: map_idx %d large than %d\n",
+				   (int)map_idx, (int)nr_maps - 1);
+			return -EINVAL;
+		}
+
+		prog->reloc_desc[i].insn_idx = insn_idx;
+		prog->reloc_desc[i].map_idx = map_idx;
+	}
+	return 0;
+}
+
+static int bpf_object__collect_reloc(struct bpf_object *obj)
+{
+	int i, err;
+
+	if (!obj_elf_valid(obj)) {
+		pr_warning("Internal error: elf object is closed\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < obj->efile.nr_reloc; i++) {
+		GElf_Shdr *shdr = &obj->efile.reloc[i].shdr;
+		Elf_Data *data = obj->efile.reloc[i].data;
+		int idx = shdr->sh_info;
+		struct bpf_program *prog;
+		size_t nr_maps = obj->maps_buf_sz /
+				 sizeof(struct bpf_map_def);
+
+		if (shdr->sh_type != SHT_REL) {
+			pr_warning("internal error at %d\n", __LINE__);
+			return -EINVAL;
+		}
+
+		prog = bpf_object__find_prog_by_idx(obj, idx);
+		if (!prog) {
+			pr_warning("relocation failed: no %d section\n",
+				   idx);
+			return -ENOENT;
+		}
+
+		err = bpf_program__collect_reloc(prog, nr_maps,
+						 shdr, data,
+						 obj->efile.symbols);
+		if (err)
+			return -EINVAL;
+	}
+	return 0;
+}
+
 static int bpf_object__validate(struct bpf_object *obj)
 {
 	if (obj->kern_version == 0) {
@@ -485,6 +607,8 @@ struct bpf_object *bpf_object__open(const char *path)
 		goto out;
 	if (bpf_object__elf_collect(obj))
 		goto out;
+	if (bpf_object__collect_reloc(obj))
+		goto out;
 	if (bpf_object__validate(obj))
 		goto out;
 
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 88d62de..73f796f 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -20,4 +20,17 @@ struct bpf_object;
 struct bpf_object *bpf_object__open(const char *path);
 void bpf_object__close(struct bpf_object *object);
 
+/*
+ * We don't need __attribute__((packed)) now since it is
+ * unnecessary for 'bpf_map_def' because they are all aligned.
+ * In addition, using it will trigger -Wpacked warning message,
+ * and will be treated as an error due to -Werror.
+ */
+struct bpf_map_def {
+	unsigned int type;
+	unsigned int key_size;
+	unsigned int value_size;
+	unsigned int max_entries;
+}; 
+
 #endif
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 15/29] bpf tools: Add bpf.c/h for common bpf operations
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (13 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 14/29] bpf tools: Record map accessing instructions for each program Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-28  1:55   ` Alexei Starovoitov
  2015-05-29 14:44   ` Namhyung Kim
  2015-05-27  5:19 ` [RFC PATCH v4 16/29] bpf tools: Create eBPF maps defined in an object file Wang Nan
                   ` (13 subsequent siblings)
  28 siblings, 2 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch introduces bpf.c and bpf.h, which hold common functions
issuing bpf syscall. The goal of these two files is to hide syscall
completly from user.  Note that bpf.c and bpf.h only deal with kernel
interface. Things like structure of 'map' section in the ELF object is
not cared by of bpf.[ch].

We first introduce bpf_create_map().

Note that, since functions in bpf.[ch] are wrapper of sys_bpf, they
don't use OO style naming.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/Build |  2 +-
 tools/lib/bpf/bpf.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/bpf.h | 16 +++++++++++++++
 3 files changed, 73 insertions(+), 1 deletion(-)
 create mode 100644 tools/lib/bpf/bpf.c
 create mode 100644 tools/lib/bpf/bpf.h

diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build
index a316484..d874975 100644
--- a/tools/lib/bpf/Build
+++ b/tools/lib/bpf/Build
@@ -1 +1 @@
-libbpf-y := libbpf.o
+libbpf-y := libbpf.o bpf.o
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
new file mode 100644
index 0000000..7481923
--- /dev/null
+++ b/tools/lib/bpf/bpf.c
@@ -0,0 +1,56 @@
+/*
+ * common eBPF ELF operations.
+ *
+ * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
+ * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2015 Huawei Inc.
+ */
+
+#include <stdlib.h>
+#include <memory.h>
+#include <unistd.h>
+#include <asm/unistd.h>
+#include <linux/bpf.h>
+#include "bpf.h"
+
+/* When building perf, unistd.h is override. __NR_bpf by ourself. */
+#if defined(__i386__)
+#ifndef __NR_bpf
+# define __NR_bpf 357
+#endif
+#endif
+
+#if defined(__x86_64__)
+#ifndef __NR_bpf
+# define __NR_bpf 321
+#endif
+#endif
+
+#if defined(__aarch64__)
+#ifndef __NR_bpf
+# define __NR_bpf 280
+#endif
+#endif
+
+#ifndef __NR_bpf
+# error __NR_bpf not defined. libbpf does not support your arch.
+#endif
+
+static int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, unsigned int size)
+{
+	return syscall(__NR_bpf, cmd, attr, size);
+}
+
+int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
+		   int max_entries)
+{
+	union bpf_attr attr;
+	memset(&attr, '\0', sizeof(attr));
+	
+	attr.map_type = map_type;
+	attr.key_size = key_size;
+	attr.value_size = value_size;
+	attr.max_entries = max_entries;
+
+	return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
+}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
new file mode 100644
index 0000000..28f7942
--- /dev/null
+++ b/tools/lib/bpf/bpf.h
@@ -0,0 +1,16 @@
+/*
+ * common eBPF ELF operations.
+ *
+ * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
+ * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2015 Huawei Inc.
+ */
+#ifndef __BPF_BPF_H
+#define __BPF_BPF_H
+
+#include <linux/bpf.h>
+
+int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
+		   int max_entries);
+
+#endif
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 16/29] bpf tools: Create eBPF maps defined in an object file
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (14 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 15/29] bpf tools: Add bpf.c/h for common bpf operations Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-28  1:57   ` Alexei Starovoitov
  2015-05-27  5:19 ` [RFC PATCH v4 17/29] bpf tools: Relocate eBPF programs Wang Nan
                   ` (12 subsequent siblings)
  28 siblings, 1 reply; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch creates maps based on 'map' section in object file using
bpf_create_map(), and store the fds into an array in
'struct bpf_object'. Since the byte order of the object may differ
from the host, swap map definition before processing.

This is the first patch in 'loading' phase. Previous patches parse ELF
object file and create needed data structure, but doesn't play with
kernel. They belong to 'opening' phase.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h |  4 +++
 2 files changed, 88 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 3a7ff7d..fe4d282 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -21,6 +21,7 @@
 #include <gelf.h>
 
 #include "libbpf.h"
+#include "bpf.h"
 
 #define __printf(a, b)	__attribute__((format(printf, a, b)))
 
@@ -108,6 +109,7 @@ struct bpf_object {
 
 	struct bpf_program *programs;
 	size_t nr_programs;
+	int *maps_fds;
 
 	/*
 	 * Information when doing elf related work. Only valid if fd
@@ -534,6 +536,57 @@ bpf_program__collect_reloc(struct bpf_program *prog,
 	return 0;
 }
 
+static int
+bpf_object__create_maps(struct bpf_object *obj)
+{
+	unsigned int i;
+	size_t nr_maps;
+	int *pfd;
+
+	nr_maps = obj->maps_buf_sz / sizeof(struct bpf_map_def);
+	if (!obj->maps_buf || !nr_maps) {
+		pr_debug("don't need create maps for %s\n",
+			 obj->path);
+		return 0;
+	}
+
+	obj->maps_fds = malloc(sizeof(int) * nr_maps);
+	if (!obj->maps_fds) {
+		pr_warning("realloc perf_bpf_maps_fds failed\n");
+		return -ENOMEM;
+	}
+
+	/* fill all fd with -1 */
+	memset(obj->maps_fds, 0xff, sizeof(int) * nr_maps);
+	
+	pfd = obj->maps_fds;
+	for (i = 0; i < nr_maps; i++) {
+		struct bpf_map_def def;
+
+		def = *(struct bpf_map_def *)(obj->maps_buf +
+				i * sizeof(struct bpf_map_def));
+
+		*pfd = bpf_create_map(def.type,
+				      def.key_size,
+				      def.value_size,
+				      def.max_entries);
+		if (*pfd < 0) {
+			size_t j;
+			int err = *pfd;
+
+			pr_warning("failed to create map: %s\n",
+				   strerror(errno));
+			for (j = 0; j < i; j++)
+				zclose(obj->maps_fds[j]);
+			zfree(&obj->maps_fds);
+			return err;
+		}
+		pr_debug("create map: fd=%d\n", *pfd);
+		pfd ++;
+	}
+	return 0;
+}
+
 static int bpf_object__collect_reloc(struct bpf_object *obj)
 {
 	int i, err;
@@ -619,6 +672,36 @@ out:
 	return NULL;
 }
 
+int bpf_object__unload(struct bpf_object *obj)
+{
+	size_t i;
+	size_t sz = sizeof(struct bpf_map_def);
+
+	if (!obj)
+		return -EINVAL;
+
+	for (i = 0; i < obj->maps_buf_sz; i += sz)
+		zclose(obj->maps_fds[i]);
+	zfree(&obj->maps_fds);
+
+	return 0;
+}
+
+int bpf_object__load(struct bpf_object *obj)
+{
+	if (!obj)
+		return -EINVAL;
+
+	if (bpf_object__create_maps(obj))
+		goto out;
+
+	return 0;
+out:
+	bpf_object__unload(obj);
+	pr_warning("failed to load object '%s'\n", obj->path);
+	return -EINVAL;
+}
+
 void bpf_object__close(struct bpf_object *obj)
 {
 	size_t i;
@@ -627,6 +710,7 @@ void bpf_object__close(struct bpf_object *obj)
 		return;
 
 	bpf_object__elf_finish(obj);
+	bpf_object__unload(obj);
 
 	zfree(&obj->maps_buf);
 
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 73f796f..716e6df 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -20,6 +20,10 @@ struct bpf_object;
 struct bpf_object *bpf_object__open(const char *path);
 void bpf_object__close(struct bpf_object *object);
 
+/* Load/unload object into/from kernel */
+int bpf_object__load(struct bpf_object *obj);
+int bpf_object__unload(struct bpf_object *obj);
+
 /*
  * We don't need __attribute__((packed)) now since it is
  * unnecessary for 'bpf_map_def' because they are all aligned.
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 17/29] bpf tools: Relocate eBPF programs
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (15 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 16/29] bpf tools: Create eBPF maps defined in an object file Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-06-01  5:32   ` Namhyung Kim
  2015-05-27  5:19 ` [RFC PATCH v4 18/29] bpf tools: Introduce bpf_load_program() to bpf.c Wang Nan
                   ` (11 subsequent siblings)
  28 siblings, 1 reply; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

If an eBPF program access a map, LLVM generates a relocated load
instruction. To enable the usage of that map, relocation must be done
by replacing original instructions by map loading instructions.

Based on relocation description collected during 'opening' phase, this
patch replaces the instructions with map loading with correct map fd.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index fe4d282..f2071ae 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -587,6 +587,53 @@ bpf_object__create_maps(struct bpf_object *obj)
 	return 0;
 }
 
+static int
+bpf_program__relocate(struct bpf_program *prog, int *maps_fds)
+{
+	int i;
+
+	if (!prog || !prog->reloc_desc)
+		return 0;
+
+	for (i = 0; i < prog->nr_reloc; i++) {
+		int insn_idx, map_idx;
+		struct bpf_insn *insns = prog->insns;
+
+		insn_idx = prog->reloc_desc[i].insn_idx;
+		map_idx = prog->reloc_desc[i].map_idx;
+
+		if (insn_idx >= (int)prog->insns_cnt) {
+			pr_warning("relocation out of range: '%s'\n",
+				   prog->section_name);
+			return -ERANGE;
+		}
+		insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
+		insns[insn_idx].imm = maps_fds[map_idx];
+	}
+
+	return 0;
+}
+
+
+static int
+bpf_object__relocate(struct bpf_object *obj)
+{
+	struct bpf_program *prog;
+	size_t i;
+	int err;
+
+	for (i = 0; i < obj->nr_programs; i++) {
+		prog = &obj->programs[i];
+
+		if ((err = bpf_program__relocate(prog, obj->maps_fds))) {
+			pr_warning("failed to relocate '%s'\n",
+				   prog->section_name);
+			return err;
+		}
+	}
+	return 0;
+}
+
 static int bpf_object__collect_reloc(struct bpf_object *obj)
 {
 	int i, err;
@@ -694,6 +741,8 @@ int bpf_object__load(struct bpf_object *obj)
 
 	if (bpf_object__create_maps(obj))
 		goto out;
+	if (bpf_object__relocate(obj))
+		goto out;
 
 	return 0;
 out:
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 18/29] bpf tools: Introduce bpf_load_program() to bpf.c
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (16 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 17/29] bpf tools: Relocate eBPF programs Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-28  2:14   ` Alexei Starovoitov
  2015-05-27  5:19 ` [RFC PATCH v4 19/29] bpf tools: Load eBPF programs in object files into kernel Wang Nan
                   ` (10 subsequent siblings)
  28 siblings, 1 reply; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

bpf_load_program() can be used to load bpf program into kernel. To make
loading faster, first try to load without logbuf. Try again with logbuf
if the first try failed.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/bpf.c | 34 ++++++++++++++++++++++++++++++++++
 tools/lib/bpf/bpf.h |  7 +++++++
 2 files changed, 41 insertions(+)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 7481923..d2002da 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -36,6 +36,11 @@
 # error __NR_bpf not defined. libbpf does not support your arch.
 #endif
 
+static __u64 ptr_to_u64(void *ptr)
+{
+	return (__u64) (unsigned long) ptr;
+}
+
 static int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, unsigned int size)
 {
 	return syscall(__NR_bpf, cmd, attr, size);
@@ -54,3 +59,32 @@ int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
 
 	return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
 }
+
+int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
+		     size_t insns_cnt, char *license,
+		     u32 kern_version, char *log_buf, size_t log_buf_sz)
+{
+	int fd;
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.prog_type = type;
+	attr.insn_cnt = (__u32)insns_cnt;
+	attr.insns = ptr_to_u64(insns);
+	attr.license = ptr_to_u64(license);
+	attr.log_buf = ptr_to_u64(NULL);
+	attr.log_size = 0;
+	attr.log_level = 0;
+	attr.kern_version = kern_version;
+
+	fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+	if (fd >= 0 || !log_buf || !log_buf_sz)
+		return fd;
+
+	/* Try again with log */
+	attr.log_buf = ptr_to_u64(log_buf);
+	attr.log_size = log_buf_sz;
+	attr.log_level = 1;
+	log_buf[0] = 0;
+	return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 28f7942..854b736 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -13,4 +13,11 @@
 int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
 		   int max_entries);
 
+/* Recommend log buffer size */
+#define BPF_LOG_BUF_SIZE 65536
+int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
+		     size_t insns_cnt, char *license,
+		     u32 kern_version, char *log_buf,
+		     size_t log_buf_sz);
+
 #endif
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 19/29] bpf tools: Load eBPF programs in object files into kernel
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (17 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 18/29] bpf tools: Introduce bpf_load_program() to bpf.c Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 20/29] bpf tools: Introduce accessors for struct bpf_program Wang Nan
                   ` (9 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch utilizes previous introduced bpf_load_program to load
programs in the ELF file into kernel. Result is stored in 'fd' field
in 'struct bpf_program'.

During loading, it allocs a log buffer and free it before return.
Note that that buffer is not passed to bpf_load_program() if the first
loading try is successful. Doesn't use a statically allocated log
buffer to avoid potention multi-thread problem.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index f2071ae..02fc880 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -99,6 +99,8 @@ struct bpf_program {
 		int map_idx;
 	} *reloc_desc;
 	int nr_reloc;
+
+	int fd;
 };
 
 struct bpf_object {
@@ -130,11 +132,20 @@ struct bpf_object {
 };
 #define obj_elf_valid(o)	((o)->efile.fd >= 0)
 
+static void bpf_program__unload(struct bpf_program *prog)
+{
+	if (!prog)
+		return;
+
+	zclose(prog->fd);
+}
+
 static void bpf_program__clear(struct bpf_program *prog)
 {
 	if (!prog)
 		return;
 
+	bpf_program__unload(prog);
 	zfree(&prog->section_name);
 	zfree(&prog->insns);
 	zfree(&prog->reloc_desc);
@@ -194,6 +205,7 @@ bpf_program__new(struct bpf_object *obj, void *data, size_t size,
 	memcpy(prog->insns, data,
 	       prog->insns_cnt * sizeof(struct bpf_insn));
 	prog->idx = idx;
+	prog->fd = -1;
 
 	return prog;
 out:
@@ -672,6 +684,64 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
 	return 0;
 }
 
+static int
+bpf_program__load(struct bpf_program *prog,
+		  char *license, u32 kern_version)
+{
+	int fd, err;
+	char *log_buf;
+
+	log_buf = malloc(BPF_LOG_BUF_SIZE);
+	if (!log_buf)
+		pr_warning("Alloc log buffer for bpf loader error, continue without log\n");
+
+	fd = bpf_load_program(BPF_PROG_TYPE_KPROBE, prog->insns,
+			      prog->insns_cnt, license,
+			      kern_version, log_buf,
+			      BPF_LOG_BUF_SIZE);
+
+	if (fd >= 0) {
+		prog->fd = fd;
+		pr_debug("load bpf program '%s': fd = %d\n",
+			 prog->section_name, prog->fd);
+		err = 0;
+		goto out;
+	}
+
+	err = -EINVAL;
+	pr_warning("load bpf program '%s' failed: %s\n",
+		   prog->section_name, strerror(errno));
+
+	if (log_buf) {
+		pr_warning("bpf: load: failed to load program '%s':\n",
+			   prog->section_name);
+		pr_warning("-- BEGIN DUMP LOG ---\n");
+		pr_warning("%s\n", log_buf);
+		pr_warning("-- END LOG --\n");
+	}
+
+out:
+	free(log_buf);
+	return err;
+}
+
+static int
+bpf_object__load_progs(struct bpf_object *obj)
+{
+	size_t i;
+	int err;
+
+	for (i = 0; i < obj->nr_programs; i++) {
+		err = bpf_program__load(&obj->programs[i],
+					obj->license,
+					obj->kern_version);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+
 static int bpf_object__validate(struct bpf_object *obj)
 {
 	if (obj->kern_version == 0) {
@@ -731,6 +801,9 @@ int bpf_object__unload(struct bpf_object *obj)
 		zclose(obj->maps_fds[i]);
 	zfree(&obj->maps_fds);
 
+	for (i = 0; i < obj->nr_programs; i++)
+		bpf_program__unload(&obj->programs[i]);
+
 	return 0;
 }
 
@@ -743,6 +816,8 @@ int bpf_object__load(struct bpf_object *obj)
 		goto out;
 	if (bpf_object__relocate(obj))
 		goto out;
+	if (bpf_object__load_progs(obj))
+		goto out;
 
 	return 0;
 out:
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 20/29] bpf tools: Introduce accessors for struct bpf_program
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (18 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 19/29] bpf tools: Load eBPF programs in object files into kernel Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 21/29] bpf tools: Introduce accessors for struct bpf_object Wang Nan
                   ` (8 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch introduces accessors for user of libbpf to retrive section
name and fd of a opened/loaded eBPF program. 'struct bpf_prog_handler'
is used for that purpose. Accessors of programs section name and file
descriptor are provided. Set/get private data are also impelmented.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h | 25 +++++++++++++++
 2 files changed, 107 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 02fc880..a577f3e 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -101,6 +101,10 @@ struct bpf_program {
 	int nr_reloc;
 
 	int fd;
+
+	struct bpf_object *obj;
+	void *priv;
+	bpf_program_clear_priv_t clear_priv;
 };
 
 struct bpf_object {
@@ -145,6 +149,12 @@ static void bpf_program__clear(struct bpf_program *prog)
 	if (!prog)
 		return;
 
+	if (prog->clear_priv)
+		prog->clear_priv(prog, prog->priv);
+
+	prog->priv = NULL;
+	prog->clear_priv = NULL;
+
 	bpf_program__unload(prog);
 	zfree(&prog->section_name);
 	zfree(&prog->insns);
@@ -206,6 +216,7 @@ bpf_program__new(struct bpf_object *obj, void *data, size_t size,
 	       prog->insns_cnt * sizeof(struct bpf_insn));
 	prog->idx = idx;
 	prog->fd = -1;
+	prog->obj = obj;
 
 	return prog;
 out:
@@ -844,3 +855,74 @@ void bpf_object__close(struct bpf_object *obj)
 
 	free(obj);
 }
+
+struct bpf_program *
+bpf_program__next(struct bpf_program *prev, struct bpf_object *obj)
+{
+	size_t idx;
+
+	if (!obj->programs)
+		return NULL;
+	/* First handler */
+	if (prev == NULL)
+		return (&obj->programs[0]);
+
+	if (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;
+	return &obj->programs[idx];
+}
+
+int bpf_program__set_private(struct bpf_program *prog,
+			     void *priv,
+			     bpf_program_clear_priv_t clear_priv)
+{
+	if (prog->priv && prog->clear_priv)
+		prog->clear_priv(prog, prog->priv);
+
+	prog->priv = priv;
+	prog->clear_priv = clear_priv;
+	return 0;
+}
+
+int bpf_program__get_private(struct bpf_program *prog, void **ppriv)
+{
+	*ppriv = prog->priv;
+	return 0;
+}
+
+int bpf_program__get_title(struct bpf_program *prog,
+			   const char **ptitle, bool dup)
+{
+	const char *title;
+	
+	if (!ptitle)
+		return -EINVAL;
+
+	title = prog->section_name;
+	if (dup) {
+		title = strdup(title);
+		if (!title) {
+			pr_warning("failed to strdup program title\n");
+			*ptitle = NULL;
+			return -ENOMEM;
+		}
+	}
+
+	*ptitle = title;
+	return 0;
+}
+
+int bpf_program__get_fd(struct bpf_program *prog, int *pfd)
+{
+	if (!pfd)
+		return -EINVAL;
+
+	*pfd = prog->fd;
+	return 0;
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 716e6df..8276735 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -9,6 +9,7 @@
 #define __BPF_LIBBPF_H
 
 #include <stdio.h>
+#include <stdbool.h>
 
 void libbpf_set_print(int (*warn)(const char *format, ...),
 		      int (*info)(const char *format, ...),
@@ -24,6 +25,30 @@ void bpf_object__close(struct bpf_object *object);
 int bpf_object__load(struct bpf_object *obj);
 int bpf_object__unload(struct bpf_object *obj);
 
+/* Accessors of bpf_program. */
+struct bpf_program;
+struct bpf_program *bpf_program__next(struct bpf_program *prog,
+				      struct bpf_object *obj);
+
+#define bpf_object__for_each_program(pos, obj)			\
+	for ((pos) = bpf_program__next(NULL, (obj));	\
+	     (pos) != NULL; 				\
+	     (pos) = bpf_program__next((pos), (obj)))
+
+typedef void (*bpf_program_clear_priv_t)(struct bpf_program *,
+					 void *);
+
+int bpf_program__set_private(struct bpf_program *prog, void *priv,
+			     bpf_program_clear_priv_t clear_priv);
+
+int bpf_program__get_private(struct bpf_program *prog,
+			     void **ppriv);
+
+int bpf_program__get_title(struct bpf_program *prog,
+			   const char **ptitle, bool dup);
+
+int bpf_program__get_fd(struct bpf_program *prog, int *pfd);
+
 /*
  * We don't need __attribute__((packed)) now since it is
  * unnecessary for 'bpf_map_def' because they are all aligned.
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 21/29] bpf tools: Introduce accessors for struct bpf_object
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (19 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 20/29] bpf tools: Introduce accessors for struct bpf_program Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 22/29] bpf tools: Link all bpf objects onto a list Wang Nan
                   ` (7 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch add an accessor which allows caller to get count of programs
in an object file.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 9 +++++++++
 tools/lib/bpf/libbpf.h | 3 +++
 2 files changed, 12 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index a577f3e..e5084fe 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -856,6 +856,15 @@ void bpf_object__close(struct bpf_object *obj)
 	free(obj);
 }
 
+int bpf_object__get_prog_cnt(struct bpf_object *obj, size_t *pcnt)
+{
+	if (!obj || !pcnt)
+		return -EINVAL;
+
+	*pcnt = obj->nr_programs;
+	return 0;
+}
+
 struct bpf_program *
 bpf_program__next(struct bpf_program *prev, struct bpf_object *obj)
 {
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 8276735..84c83d4 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -25,6 +25,9 @@ void bpf_object__close(struct bpf_object *object);
 int bpf_object__load(struct bpf_object *obj);
 int bpf_object__unload(struct bpf_object *obj);
 
+/* Accessors of bpf_object */
+int bpf_object__get_prog_cnt(struct bpf_object *obj, size_t *pcnt);
+
 /* Accessors of bpf_program. */
 struct bpf_program;
 struct bpf_program *bpf_program__next(struct bpf_program *prog,
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 22/29] bpf tools: Link all bpf objects onto a list
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (20 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 21/29] bpf tools: Introduce accessors for struct bpf_object Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 23/29] perf tools: Make perf depend on libbpf Wang Nan
                   ` (6 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

To prevent caller from creating additional structures to hold
pointers of 'struct bpf_object', this patch link all such
structures onto a list (hidden to user). bpf_object__for_each() is
introduced to allow users iterate over each objects.
bpf_object__for_each() is safe even user close the object during
iteration.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 32 ++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h |  7 +++++++
 2 files changed, 39 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e5084fe..e2b41b7 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -17,6 +17,7 @@
 #include <asm/unistd.h>
 #include <linux/kernel.h>
 #include <linux/bpf.h>
+#include <linux/list.h>
 #include <libelf.h>
 #include <gelf.h>
 
@@ -107,6 +108,8 @@ struct bpf_program {
 	bpf_program_clear_priv_t clear_priv;
 };
 
+static LIST_HEAD(bpf_objects_list);
+
 struct bpf_object {
 	char license[64];
 	u32 kern_version;
@@ -132,6 +135,12 @@ struct bpf_object {
 		} *reloc;
 		int nr_reloc;
 	} efile;
+	/*
+	 * All loaded bpf_object is linked in a list, which is
+	 * hidden to caller. bpf_objects__<func> handlers deal with
+	 * all objects.
+	 */
+	struct list_head list;
 	char path[];
 };
 #define obj_elf_valid(o)	((o)->efile.fd >= 0)
@@ -236,6 +245,9 @@ static struct bpf_object *bpf_object__new(const char *path)
 
 	strcpy(obj->path, path);
 	obj->efile.fd = -1;
+
+	INIT_LIST_HEAD(&obj->list);
+	list_add(&obj->list, &bpf_objects_list);
 	return obj;
 }
 
@@ -853,6 +865,7 @@ void bpf_object__close(struct bpf_object *obj)
 		bpf_program__clear(&obj->programs[i]);
 	zfree(&obj->programs);
 
+	list_del(&obj->list);
 	free(obj);
 }
 
@@ -865,6 +878,25 @@ int bpf_object__get_prog_cnt(struct bpf_object *obj, size_t *pcnt)
 	return 0;
 }
 
+struct bpf_object *
+bpf_object__next(struct bpf_object *prev)
+{
+	struct bpf_object *next;
+
+	if (!prev)
+		next = list_first_entry(&bpf_objects_list,
+					struct bpf_object,
+					list);
+	else
+		next = list_next_entry(prev, list);
+
+	/* Empty list is noticed here so don't need checking on entry. */
+	if (&next->list == &bpf_objects_list)
+		return NULL;
+
+	return next;
+}
+
 struct bpf_program *
 bpf_program__next(struct bpf_program *prev, struct bpf_object *obj)
 {
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 84c83d4..fa271ec 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -28,6 +28,13 @@ int bpf_object__unload(struct bpf_object *obj);
 /* Accessors of bpf_object */
 int bpf_object__get_prog_cnt(struct bpf_object *obj, size_t *pcnt);
 
+struct bpf_object *bpf_object__next(struct bpf_object *prev);
+#define bpf_object__for_each(pos, tmp)			\
+	for ((pos) = bpf_object__next(NULL),		\
+		(tmp) = bpf_object__next(pos);		\
+	     (pos) != NULL;				\
+	     (pos) = (tmp), (tmp) = bpf_object__next(tmp))
+
 /* Accessors of bpf_program. */
 struct bpf_program;
 struct bpf_program *bpf_program__next(struct bpf_program *prog,
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 23/29] perf tools: Make perf depend on libbpf
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (21 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 22/29] bpf tools: Link all bpf objects onto a list Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27  5:19 ` [RFC PATCH v4 24/29] perf record: Enable passing bpf object file to --event Wang Nan
                   ` (5 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

By adding libbpf into perf's Makefile, this patch enable perf to
build libbpf during building if libelf is found and NO_LIBELF is not
set. The newly introduced code is similar to libapi and libtraceevent
building in Makefile.perf.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/perf/Makefile.perf | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index c43a205..45f10da 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -123,6 +123,7 @@ STRIP   = strip
 
 LIB_DIR          = $(srctree)/tools/lib/api/
 TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
+BPF_DIR = $(srctree)/tools/lib/bpf/
 
 # include config/Makefile by default and rule out
 # non-config cases
@@ -158,6 +159,7 @@ strip-libs = $(filter-out -l%,$(1))
 
 ifneq ($(OUTPUT),)
   TE_PATH=$(OUTPUT)
+  BPF_PATH=$(OUTPUT)
 ifneq ($(subdir),)
   LIB_PATH=$(OUTPUT)/../lib/api/
 else
@@ -166,6 +168,7 @@ endif
 else
   TE_PATH=$(TRACE_EVENT_DIR)
   LIB_PATH=$(LIB_DIR)
+  BPF_PATH=$(BPF_DIR)
 endif
 
 LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
@@ -174,6 +177,8 @@ export LIBTRACEEVENT
 LIBAPI = $(LIB_PATH)libapi.a
 export LIBAPI
 
+LIBBPF = $(BPF_PATH)libbpf.a
+
 # python extension build directories
 PYTHON_EXTBUILD     := $(OUTPUT)python_ext_build/
 PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
@@ -225,6 +230,11 @@ export PERL_PATH
 LIB_FILE=$(OUTPUT)libperf.a
 
 PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT)
+ifndef NO_LIBELF
+  ifeq ($(feature-libelf), 1)
+    PERFLIBS += $(LIBBPF)
+  endif
+endif
 
 # We choose to avoid "if .. else if .. else .. endif endif"
 # because maintaining the nesting to match is a pain.  If
@@ -387,6 +397,13 @@ $(LIBAPI)-clean:
 	$(call QUIET_CLEAN, libapi)
 	$(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
 
+$(LIBBPF): FORCE
+	$(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a
+
+$(LIBBPF)-clean:
+	$(call QUIET_CLEAN, libbpf)
+	$(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null
+
 help:
 	@echo 'Perf make targets:'
 	@echo '  doc		- make *all* documentation (see below)'
@@ -525,7 +542,7 @@ config-clean:
 	$(call QUIET_CLEAN, config)
 	$(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null
 
-clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean
+clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean config-clean
 	$(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
 	$(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
 	$(Q)$(RM) .config-detected
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 24/29] perf record: Enable passing bpf object file to --event
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (22 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 23/29] perf tools: Make perf depend on libbpf Wang Nan
@ 2015-05-27  5:19 ` Wang Nan
  2015-05-27  5:20 ` [RFC PATCH v4 25/29] perf tools: Parse probe points of eBPF programs during preparation Wang Nan
                   ` (4 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:19 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

By introducing new rules in tools/perf/util/parse-events.[ly], this
patch enables 'perf record --event bpf_file.o' to select events by
an eBPF object file. It calls parse_events_load_bpf() to load that
file, which uses bpf__prepare_load() and finally calls
bpf_object__open() for the object files.

Instead of introducing evsel to evlist during parsing, events
selected by eBPF object files are appended separately. The reason
is:

 1. During parsing, the probing points have not been initialized.

 2. Currently we are unable to call add_perf_probe_events() twice,
    therefore we have to wait until all such events are collected,
    then probe all points by one call.

The real probing and selecting is reside in following patches.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/perf/util/Build          |  1 +
 tools/perf/util/bpf-loader.c   | 60 ++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/bpf-loader.h   | 11 ++++++++
 tools/perf/util/debug.c        |  5 ++++
 tools/perf/util/debug.h        |  1 +
 tools/perf/util/parse-events.c | 16 +++++++++++
 tools/perf/util/parse-events.h |  2 ++
 tools/perf/util/parse-events.l |  5 +++-
 tools/perf/util/parse-events.y | 18 ++++++++++++-
 9 files changed, 117 insertions(+), 2 deletions(-)
 create mode 100644 tools/perf/util/bpf-loader.c
 create mode 100644 tools/perf/util/bpf-loader.h

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 797490a..609f6d6 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -75,6 +75,7 @@ libperf-$(CONFIG_X86) += tsc.o
 libperf-y += cloexec.o
 libperf-y += thread-stack.o
 
+libperf-$(CONFIG_LIBELF) += bpf-loader.o
 libperf-$(CONFIG_LIBELF) += symbol-elf.o
 libperf-$(CONFIG_LIBELF) += probe-event.o
 
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
new file mode 100644
index 0000000..eef15f3
--- /dev/null
+++ b/tools/perf/util/bpf-loader.c
@@ -0,0 +1,60 @@
+/*
+ * bpf-loader.c
+ *
+ * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2015 Huawei Inc.
+ */
+
+#include <bpf/libbpf.h>
+#include "perf.h"
+#include "debug.h"
+#include "bpf-loader.h"
+
+#define DEFINE_PRINT_FN(name, level) \
+static int libbpf_##name(const char *fmt, ...)	\
+{						\
+	va_list args;				\
+	int ret;				\
+						\
+	va_start(args, fmt);			\
+	ret = veprintf(level, verbose, pr_fmt(fmt), args);\
+	va_end(args);				\
+	return ret;				\
+}
+
+DEFINE_PRINT_FN(warning, 0)
+DEFINE_PRINT_FN(info, 0)
+DEFINE_PRINT_FN(debug, 1)
+
+static bool libbpf_initialized = false;
+
+int bpf__prepare_load(const char *filename)
+{
+	struct bpf_object *obj;
+
+	if (!libbpf_initialized)
+		libbpf_set_print(libbpf_warning,
+				 libbpf_info,
+				 libbpf_debug);
+	
+	obj = bpf_object__open(filename);
+	if (!obj) {
+		pr_err("bpf: failed to load %s\n", filename);
+		return -EINVAL;
+	}
+
+	/*
+	 * Throw object pointer away: it will be retrived using
+	 * bpf_objects iterater.
+	 */
+
+	return 0;
+}
+
+void bpf__clear(void)
+{
+	struct bpf_object *obj, *tmp;
+
+	bpf_object__for_each(obj, tmp)
+		bpf_object__close(obj);
+}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
new file mode 100644
index 0000000..d5c22da
--- /dev/null
+++ b/tools/perf/util/bpf-loader.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2015, Huawei Inc.
+ */
+#ifndef __BPF_LOADER_H
+#define __BPF_LOADER_H
+
+int bpf__prepare_load(const char *filename);
+
+void bpf__clear(void);
+#endif
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 2da5581..86d9c73 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -36,6 +36,11 @@ static int _eprintf(int level, int var, const char *fmt, va_list args)
 	return ret;
 }
 
+int veprintf(int level, int var, const char *fmt, va_list args)
+{
+	return _eprintf(level, var, fmt, args);
+}
+
 int eprintf(int level, int var, const char *fmt, ...)
 {
 	va_list args;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index caac2fd..8b9a088 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -50,6 +50,7 @@ void pr_stat(const char *fmt, ...);
 
 int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
 int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __attribute__((format(printf, 4, 5)));
+int veprintf(int level, int var, const char *fmt, va_list args);
 
 int perf_debug_option(const char *str);
 
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index be06553..6030ea3 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -17,6 +17,7 @@
 #include "parse-events-flex.h"
 #include "pmu.h"
 #include "thread_map.h"
+#include "bpf-loader.h"
 
 #define MAX_NAME_LEN 100
 
@@ -471,6 +472,21 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
 		return add_tracepoint_event(list, idx, sys, event);
 }
 
+int parse_events_load_bpf(struct list_head *list __maybe_unused,
+			  int *idx __maybe_unused,
+			  char *bpf_file_name)
+{
+	/*
+	 * Currently don't link any event to list. BPF object files
+	 * should be saved to a seprated list and processed together.
+	 *
+	 * Things could be changed if we solve perf probe reentering
+	 * problem. After that probe events file by file is possible.
+	 * However, probing cost is still need to be considered.
+	 */
+	return bpf__prepare_load(bpf_file_name);
+}
+
 static int
 parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
 {
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 52a2dda..a8a0f01 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -99,6 +99,8 @@ int parse_events__modifier_group(struct list_head *list, char *event_mod);
 int parse_events_name(struct list_head *list, char *name);
 int parse_events_add_tracepoint(struct list_head *list, int *idx,
 				char *sys, char *event);
+int parse_events_load_bpf(struct list_head *list, int *idx,
+			  char *bpf_file_name);
 int parse_events_add_numeric(struct list_head *list, int *idx,
 			     u32 type, u64 config,
 			     struct list_head *head_config);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 8895cf3..a35cd4d 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -94,6 +94,7 @@ static int term(yyscan_t scanner, int type)
 group		[^,{}/]*[{][^}]*[}][^,{}/]*
 event_pmu	[^,{}/]+[/][^/]*[/][^,{}/]*
 event		[^,{}/]+
+bpf_file	.*\.(o|bpf)
 
 num_dec		[0-9]+
 num_hex		0x[a-fA-F0-9]+
@@ -131,7 +132,8 @@ modifier_bp	[rwx]{1,3}
 		}
 
 {event_pmu}	|
-{event}		{
+{event}		|
+{bpf_file}	{
 			str(yyscanner, PE_EVENT_NAME);
 			BEGIN(INITIAL); yyless(0);
 			return PE_EVENT_NAME;
@@ -229,6 +231,7 @@ r{num_raw_hex}		{ return raw(yyscanner); }
 
 {modifier_event}	{ return str(yyscanner, PE_MODIFIER_EVENT); }
 {name}			{ return pmu_str_check(yyscanner); }
+{bpf_file}		{ return str(yyscanner, PE_BPF_FILE); }
 "/"			{ BEGIN(config); return '/'; }
 -			{ return '-'; }
 ,			{ BEGIN(event); return ','; }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 72def07..e9c4861 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -43,6 +43,7 @@ static inc_group_count(struct list_head *list,
 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
 %token PE_EVENT_NAME
 %token PE_NAME
+%token PE_BPF_FILE
 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
@@ -54,6 +55,7 @@ static inc_group_count(struct list_head *list,
 %type <num> PE_RAW
 %type <num> PE_TERM
 %type <str> PE_NAME
+%type <str> PE_BPF_FILE
 %type <str> PE_NAME_CACHE_TYPE
 %type <str> PE_NAME_CACHE_OP_RESULT
 %type <str> PE_MODIFIER_EVENT
@@ -70,6 +72,7 @@ static inc_group_count(struct list_head *list,
 %type <head> event_legacy_tracepoint
 %type <head> event_legacy_numeric
 %type <head> event_legacy_raw
+%type <head> event_bpf_file
 %type <head> event_def
 %type <head> event_mod
 %type <head> event_name
@@ -199,7 +202,8 @@ event_def: event_pmu |
 	   event_legacy_mem |
 	   event_legacy_tracepoint sep_dc |
 	   event_legacy_numeric sep_dc |
-	   event_legacy_raw sep_dc
+	   event_legacy_raw sep_dc |
+	   event_bpf_file
 
 event_pmu:
 PE_NAME '/' event_config '/'
@@ -416,6 +420,18 @@ PE_RAW
 	$$ = list;
 }
 
+event_bpf_file:
+PE_BPF_FILE
+{
+	struct parse_events_evlist *data = _data;
+	struct list_head *list;
+
+	ALLOC_LIST(list);
+	ABORT_ON(parse_events_load_bpf(list, &data->idx, $1));
+	$$ = list;
+}
+
+
 start_terms: event_config
 {
 	struct parse_events_terms *data = _data;
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 25/29] perf tools: Parse probe points of eBPF programs during preparation
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (23 preceding siblings ...)
  2015-05-27  5:19 ` [RFC PATCH v4 24/29] perf record: Enable passing bpf object file to --event Wang Nan
@ 2015-05-27  5:20 ` Wang Nan
  2015-05-27  5:20 ` [RFC PATCH v4 26/29] perf record: Probe at kprobe points Wang Nan
                   ` (3 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:20 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch parses section name of each program, and creates
corresponding 'struct perf_probe_event' structure.

parse_perf_probe_command() is used to do the main parsing works.
Parsing result is stored into a global array. This is because
add_perf_probe_events() is non-reentrantable. In following patch,
add_perf_probe_events will be introduced to insert kprobes. It accepts
an array of 'struct perf_probe_event' and do all works in one call.

Define PERF_BPF_PROBE_GROUP as "perf_bpf_probe", which will be used
as group name of all eBPF probing points.

This patch utilizes bpf_program__set_private(), bind perf_probe_event
with bpf program by private field.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/perf/util/bpf-loader.c | 123 ++++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/bpf-loader.h |   2 +
 2 files changed, 124 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index eef15f3..1022729 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -9,6 +9,8 @@
 #include "perf.h"
 #include "debug.h"
 #include "bpf-loader.h"
+#include "probe-event.h"
+#include "probe-finder.h"
 
 #define DEFINE_PRINT_FN(name, level) \
 static int libbpf_##name(const char *fmt, ...)	\
@@ -28,9 +30,120 @@ DEFINE_PRINT_FN(debug, 1)
 
 static bool libbpf_initialized = false;
 
+static struct perf_probe_event probe_event_array[MAX_PROBES];
+static size_t nr_probe_events;
+
+static struct perf_probe_event *
+alloc_perf_probe_event(void)
+{
+	struct perf_probe_event *pev;
+	int n = nr_probe_events;
+	if (n >= MAX_PROBES) {
+		pr_err("bpf: too many events, increase MAX_PROBES\n");
+		return NULL;
+	}
+
+	nr_probe_events = n + 1;
+	pev = &probe_event_array[n];
+	bzero(pev, sizeof(*pev));
+	return pev;
+}
+
+struct bpf_prog_priv {
+	struct perf_probe_event *pev;
+};
+
+static void
+bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused,
+			  void *_priv)
+{
+	struct bpf_prog_priv *priv = _priv;
+	if (priv->pev)
+		clear_perf_probe_event(priv->pev);
+	free(priv);
+}
+
+static int
+config_bpf_program(struct bpf_program *prog)
+{
+	struct perf_probe_event *pev = alloc_perf_probe_event();
+	struct bpf_prog_priv *priv = NULL;
+	const char *config_str;
+	int err;
+
+	/* pr_err has been done by alloc_perf_probe_event */
+	if (!pev)
+		return -ENOMEM;
+
+	err = bpf_program__get_title(prog, &config_str, false);
+	if (err || !config_str) {
+		pr_err("bpf: unable to get title for program\n");
+		return -EINVAL;
+	}
+
+	pr_debug("bpf: config program '%s'\n", config_str);
+	err = parse_perf_probe_command(config_str, pev);
+	if (err < 0) {
+		pr_err("bpf: '%s' is not a valid config string\n",
+		       config_str);
+		/* parse failed, don't need clear pev. */
+		return -EINVAL;
+	}
+
+	if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
+		pr_err("bpf: '%s': group for event is set and not '%s'.\n",
+		       config_str, PERF_BPF_PROBE_GROUP);
+		err = -EINVAL;
+		goto errout;
+	} else if (!pev->group)
+		pev->group = strdup(PERF_BPF_PROBE_GROUP);
+
+	if (!pev->group) {
+		pr_err("bpf: strdup failed\n");
+		err = -ENOMEM;
+		goto errout;
+	}
+
+	if (!pev->event) {
+		pr_err("bpf: '%s': event name is missing\n",
+		       config_str);
+		err = -EINVAL;
+		goto errout;
+	}
+
+	pr_debug("bpf: config '%s' is ok\n", config_str);
+
+	priv = calloc(1, sizeof(*priv));
+	if (!priv) {
+		pr_err("bpf: failed to alloc memory\n");
+		err = -ENOMEM;
+		goto errout;
+	}
+
+	priv->pev = pev;
+	
+	err = bpf_program__set_private(prog, priv,
+				       bpf_prog_priv__clear);
+	if (err) {
+		pr_err("bpf: set program private failed\n");
+		err = -ENOMEM;
+		goto errout;
+	}
+	return 0;
+
+errout:
+	if (pev)
+		clear_perf_probe_event(pev);
+	if (priv)
+		free(priv);
+	return err;
+}
+
 int bpf__prepare_load(const char *filename)
 {
 	struct bpf_object *obj;
+	struct bpf_program *prog;
+	int err = 0;
 
 	if (!libbpf_initialized)
 		libbpf_set_print(libbpf_warning,
@@ -43,12 +156,20 @@ int bpf__prepare_load(const char *filename)
 		return -EINVAL;
 	}
 
+	bpf_object__for_each_program(prog, obj) {
+		err = config_bpf_program(prog);
+		if (err)
+			goto errout;
+	}
+
 	/*
 	 * Throw object pointer away: it will be retrived using
 	 * bpf_objects iterater.
 	 */
-
 	return 0;
+errout:
+	bpf_object__close(obj);
+	return err;
 }
 
 void bpf__clear(void)
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index d5c22da..43d7b99 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -5,6 +5,8 @@
 #ifndef __BPF_LOADER_H
 #define __BPF_LOADER_H
 
+#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
+
 int bpf__prepare_load(const char *filename);
 
 void bpf__clear(void);
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 26/29] perf record: Probe at kprobe points
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (24 preceding siblings ...)
  2015-05-27  5:20 ` [RFC PATCH v4 25/29] perf tools: Parse probe points of eBPF programs during preparation Wang Nan
@ 2015-05-27  5:20 ` Wang Nan
  2015-05-27  5:20 ` [RFC PATCH v4 27/29] perf record: Load all eBPF object into kernel Wang Nan
                   ` (2 subsequent siblings)
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:20 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

In this patch, kprobe points are created using add_perf_probe_events.
Since all events are already grouped together in an array, calling
add_perf_probe_events() once creates all of them.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/perf/builtin-record.c  | 14 ++++++++++++++
 tools/perf/util/bpf-loader.c | 45 ++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/bpf-loader.h |  2 ++
 3 files changed, 61 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index c3efdfb..9297800 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -27,6 +27,7 @@
 #include "util/cpumap.h"
 #include "util/thread_map.h"
 #include "util/data.h"
+#include "util/bpf-loader.h"
 
 #include <unistd.h>
 #include <sched.h>
@@ -957,6 +958,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 		usage_with_options(record_usage, record_options);
 	}
 
+	/*
+	 * bpf__probe must be called before symbol__init() because we
+	 * need init_symbol_maps. If called after symbol__init,
+	 * symbol_conf.sort_by_name won't take effect.
+	 */
+	err = bpf__probe();
+	if (err) {
+		pr_err("Probing at events in BPF object failed.\n");
+		pr_err("Try perf probe -d '*' to remove existing probe events.\n");
+		return err;
+	}
+
 	symbol__init(NULL);
 
 	if (symbol_conf.kptr_restrict)
@@ -1011,5 +1024,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 out_symbol_exit:
 	perf_evlist__delete(rec->evlist);
 	symbol__exit();
+	bpf__unprobe();
 	return err;
 }
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 1022729..f5d5f3e 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -179,3 +179,48 @@ void bpf__clear(void)
 	bpf_object__for_each(obj, tmp)
 		bpf_object__close(obj);
 }
+
+static bool is_probing = false;
+
+int bpf__unprobe(void)
+{
+	struct strlist *dellist;
+	int ret;
+
+	if (!is_probing)
+		return 0;
+
+	dellist = strlist__new(true, PERF_BPF_PROBE_GROUP ":*");
+	if (!dellist) {
+		pr_err("Failed to create dellist when unprobing\n");
+		return -ENOMEM;
+	}
+
+	ret = del_perf_probe_events(dellist);
+	strlist__delete(dellist);
+	if (ret < 0 && is_probing)
+		pr_err("  Error: failed to delete events: %s\n",
+			strerror(-ret));
+	else
+		is_probing = false;
+	return ret < 0 ? ret : 0;
+}
+
+int bpf__probe(void)
+{
+	int err;
+
+	if (nr_probe_events <= 0)
+		return 0;
+
+	err = add_perf_probe_events(probe_event_array,
+				    nr_probe_events,
+				    MAX_PROBES, 0);
+	/* add_perf_probe_events return negative when fail */
+	if (err < 0)
+		pr_err("bpf probe: failed to probe events\n");
+	else
+		is_probing = true;
+
+	return err < 0 ? err : 0;
+}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 43d7b99..1127880 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -8,6 +8,8 @@
 #define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
 
 int bpf__prepare_load(const char *filename);
+int bpf__probe(void);
+int bpf__unprobe(void);
 
 void bpf__clear(void);
 #endif
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 27/29] perf record: Load all eBPF object into kernel
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (25 preceding siblings ...)
  2015-05-27  5:20 ` [RFC PATCH v4 26/29] perf record: Probe at kprobe points Wang Nan
@ 2015-05-27  5:20 ` Wang Nan
  2015-05-27  5:20 ` [RFC PATCH v4 28/29] perf tools: Add bpf_fd field to evsel and config it Wang Nan
  2015-05-27  5:20 ` [RFC PATCH v4 29/29] perf tools: Attach eBPF program to perf event Wang Nan
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:20 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch utilizes bpf_load_object() provided by libbpf to load all
objects into kernel.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/perf/builtin-record.c  | 12 ++++++++++++
 tools/perf/util/bpf-loader.c | 19 +++++++++++++++++++
 tools/perf/util/bpf-loader.h |  1 +
 3 files changed, 32 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 9297800..4b52399 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -970,6 +970,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 		return err;
 	}
 
+	/*
+	 * bpf__probe() also calls symbol__init() if there are probe
+	 * events in bpf objects, so calling symbol_exit when failuer
+	 * is safe. If there is no probe event, bpf__load() always
+	 * success.
+	 */
+	err = bpf__load();
+	if (err) {
+		pr_err("Loading BPF programs failed\n");
+		goto out_symbol_exit;
+	}
+
 	symbol__init(NULL);
 
 	if (symbol_conf.kptr_restrict)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index f5d5f3e..f9a1ab9 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -224,3 +224,22 @@ int bpf__probe(void)
 
 	return err < 0 ? err : 0;
 }
+
+int bpf__load(void)
+{
+	struct bpf_object *obj, *tmp;
+	int err = 0;
+
+	bpf_object__for_each(obj, tmp) {
+		err = bpf_object__load(obj);
+		if (err) {
+			pr_err("bpf: load objects failed\n");
+			goto errout;
+		}
+	}
+	return 0;
+errout:
+	bpf_object__for_each(obj, tmp)
+		bpf_object__unload(obj);
+	return err;
+}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 1127880..fcc775d 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -10,6 +10,7 @@
 int bpf__prepare_load(const char *filename);
 int bpf__probe(void);
 int bpf__unprobe(void);
+int bpf__load(void);
 
 void bpf__clear(void);
 #endif
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 28/29] perf tools: Add bpf_fd field to evsel and config it
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (26 preceding siblings ...)
  2015-05-27  5:20 ` [RFC PATCH v4 27/29] perf record: Load all eBPF object into kernel Wang Nan
@ 2015-05-27  5:20 ` Wang Nan
  2015-05-27  5:20 ` [RFC PATCH v4 29/29] perf tools: Attach eBPF program to perf event Wang Nan
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:20 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

This patch adds a bpf_fd field to 'struct evsel' then introduces method
to config it. In bpf-loader, a bpf__for_each_program() function is added.
Which calls the callback function for each eBPF program with their names
and file descriptors. In evlist.c, perf_evlist__add_bpf()
is added to add all bpf events into evlist. 'perf record' calls
perf_evlist__add_bpf().

Since bpf-loader.c will not built if libelf not found, an empty
bpf__for_each_program() is defined in bpf-loader.h to avoid compiling
error.
---
 tools/perf/builtin-record.c  |  6 ++++++
 tools/perf/util/bpf-loader.c | 39 +++++++++++++++++++++++++++++++++++++++
 tools/perf/util/bpf-loader.h | 16 ++++++++++++++++
 tools/perf/util/evlist.c     | 32 ++++++++++++++++++++++++++++++++
 tools/perf/util/evlist.h     |  1 +
 tools/perf/util/evsel.c      |  1 +
 tools/perf/util/evsel.h      |  1 +
 7 files changed, 96 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4b52399..692cfe5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -982,6 +982,12 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 		goto out_symbol_exit;
 	}
 
+	err = perf_evlist__add_bpf(rec->evlist);
+	if (err < 0) {
+		pr_err("Failed to add events from BPF object(s)\n");
+		goto out_symbol_exit;
+	}
+
 	symbol__init(NULL);
 
 	if (symbol_conf.kptr_restrict)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index f9a1ab9..5d23346 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -243,3 +243,42 @@ errout:
 		bpf_object__unload(obj);
 	return err;
 }
+
+int
+bpf__for_each_program(bpf_prog_iter_callback_t func,
+		      void *arg)
+{
+	struct bpf_object *obj, *tmp;
+	struct bpf_program *prog;
+	int err;
+
+	bpf_object__for_each(obj, tmp) {
+		bpf_object__for_each_program(prog, obj) {
+			struct bpf_prog_priv *priv;
+			char *group, *event;
+			int fd;
+
+			err = bpf_program__get_private(prog,
+						       (void **)&priv);
+			if (err || !priv) {
+				pr_err("bpf: failed to get private field\n");
+				return -EINVAL;
+			}
+			err = bpf_program__get_fd(prog, &fd);
+			if (err || fd < 0) {
+				pr_err("bpf: failed to get file descriptor\n");
+				return -EINVAL;
+			}
+
+			group = priv->pev->group;
+			event = priv->pev->event;
+			err = func(group, event, fd, arg);
+			if (err) {
+				pr_err("bpf: call back failed, stop iterate\n");
+				return err;
+			}
+		}
+	}
+
+	return 0;
+}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index fcc775d..4d5eec2 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -5,6 +5,8 @@
 #ifndef __BPF_LOADER_H
 #define __BPF_LOADER_H
 
+#include <linux/compiler.h> // for __maybe_unused
+
 #define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
 
 int bpf__prepare_load(const char *filename);
@@ -13,4 +15,18 @@ int bpf__unprobe(void);
 int bpf__load(void);
 
 void bpf__clear(void);
+
+typedef int (*bpf_prog_iter_callback_t)(char *group, char *event,
+					int fd, void *arg);
+
+#ifdef HAVE_LIBELF_SUPPORT
+int bpf__for_each_program(bpf_prog_iter_callback_t func, void *arg);
+#else
+static inline int
+bpf__for_each_program(bpf_prog_iter_callback_t func __maybe_unused,
+		      void *arg __maybe_unused)
+{
+	return 0;
+}
+#endif
 #endif
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 080be93..2b997d1 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -14,6 +14,7 @@
 #include "target.h"
 #include "evlist.h"
 #include "evsel.h"
+#include "bpf-loader.h"
 #include "debug.h"
 #include <unistd.h>
 
@@ -194,6 +195,37 @@ error:
 	return -ENOMEM;
 }
 
+static int add_bpf_event(char *group, char *event, int fd,
+			 void *arg)
+{
+	struct perf_evlist *evlist = arg;
+	struct perf_evsel *pos;
+	struct list_head list;
+	int err, idx, entries;
+
+	pr_debug("add bpf event %s:%s and attach bpf program %d\n",
+		 group, event, fd);
+	INIT_LIST_HEAD(&list);
+	idx = evlist->nr_entries;
+	err = parse_events_add_tracepoint(&list, &idx, group, event);
+	
+	if (err) {
+		pr_err("Failed to add BPF event %s:%s\n",
+		       group, event);
+		return err;
+	}
+	list_for_each_entry(pos, &list, node)
+		pos->bpf_fd = fd;
+	entries = idx - evlist->nr_entries;
+	perf_evlist__splice_list_tail(evlist, &list, entries);
+	return 0;
+}
+
+int perf_evlist__add_bpf(struct perf_evlist *evlist)
+{
+	return bpf__for_each_program(add_bpf_event, evlist);
+}
+
 static int perf_evlist__add_attrs(struct perf_evlist *evlist,
 				  struct perf_event_attr *attrs, size_t nr_attrs)
 {
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index b5cce95..032f04d 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -68,6 +68,7 @@ void perf_evlist__delete(struct perf_evlist *evlist);
 
 void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
 int perf_evlist__add_default(struct perf_evlist *evlist);
+int perf_evlist__add_bpf(struct perf_evlist *evlist);
 int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
 				     struct perf_event_attr *attrs, size_t nr_attrs);
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 33e3fd8..04d60a7 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -205,6 +205,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
 	evsel->leader	   = evsel;
 	evsel->unit	   = "";
 	evsel->scale	   = 1.0;
+	evsel->bpf_fd	   = -1;
 	INIT_LIST_HEAD(&evsel->node);
 	perf_evsel__object.init(evsel);
 	evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index e486151..ff1f634 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -100,6 +100,7 @@ struct perf_evsel {
 	int			sample_read;
 	struct perf_evsel	*leader;
 	char			*group_name;
+	int			bpf_fd;
 };
 
 union u64_swap {
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [RFC PATCH v4 29/29] perf tools: Attach eBPF program to perf event
  2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
                   ` (27 preceding siblings ...)
  2015-05-27  5:20 ` [RFC PATCH v4 28/29] perf tools: Add bpf_fd field to evsel and config it Wang Nan
@ 2015-05-27  5:20 ` Wang Nan
  28 siblings, 0 replies; 62+ messages in thread
From: Wang Nan @ 2015-05-27  5:20 UTC (permalink / raw)
  To: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt
  Cc: lizefan, linux-kernel, pi3orama

In this patch PERF_EVENT_IOC_SET_BPF ioctl is used to attach eBPF
program to a newly created perf event. The file descriptor of the
eBPF program is passed to perf record using previous patches, and
stored into evsel->bpf_fd.

It is possible that different perf event are created for one kprobe
events for different CPUs. In this case, when trying to call the
ioctl, EEXIST will be return. This patch doesn't treat it as an error.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/perf/util/evsel.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 04d60a7..3b94c66 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1201,6 +1201,22 @@ retry_open:
 					  err);
 				goto try_fallback;
 			}
+
+			if (evsel->bpf_fd >= 0) {
+				int evt_fd = FD(evsel, cpu, thread);
+				int bpf_fd = evsel->bpf_fd;
+
+				err = ioctl(evt_fd,
+					    PERF_EVENT_IOC_SET_BPF,
+					    bpf_fd);
+				if (err && errno != EEXIST) {
+					pr_err("failed to attach bpf fd %d: %s\n",
+					       bpf_fd, strerror(errno));
+					err = -EINVAL;
+					goto out_close;
+				}
+			}
+
 			set_rlimit = NO_CHANGE;
 
 			/*
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 01/29] tools: Add __aligned_u64 to types.h
  2015-05-27  5:19 ` [RFC PATCH v4 01/29] tools: Add __aligned_u64 to types.h Wang Nan
@ 2015-05-27 13:00   ` Arnaldo Carvalho de Melo
  2015-05-28  0:28     ` Wangnan (F)
  0 siblings, 1 reply; 62+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-27 13:00 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, namhyung, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama

Em Wed, May 27, 2015 at 05:19:36AM +0000, Wang Nan escreveu:
> Following patches will introduce linux/bpf.h to a new libbpf library,
> which requires definition of __aligned_u64. This patch add it to the
> common types.h for tools.

This was already merged, see:

http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/log/tools?h=perf/core

More specifically:

http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/commit/tools?h=perf/core&id=70ba6b8f975bcff56e180e2c7550d2302fcbf923

So you can drop it from your patchset.

BTW, where are you basing your work?

If you do it over tip/perf/core you may find some of the trivial stuff
being added there, like this one.
 
- Arnaldo

> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> ---
>  tools/include/linux/types.h | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h
> index b5cf25e..10a2cdc 100644
> --- a/tools/include/linux/types.h
> +++ b/tools/include/linux/types.h
> @@ -60,6 +60,11 @@ typedef __u32 __bitwise __be32;
>  typedef __u64 __bitwise __le64;
>  typedef __u64 __bitwise __be64;
>  
> +/* Taken from uapi/linux/types.h. Required by linux/bpf.h */
> +#ifndef __aligned_u64
> +# define __aligned_u64 __u64 __attribute__((aligned(8)))
> +#endif
> +
>  struct list_head {
>  	struct list_head *next, *prev;
>  };
> -- 
> 1.8.3.4

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 02/29] perf tools: Move linux/kernel.h to tools/include
  2015-05-27  5:19 ` [RFC PATCH v4 02/29] perf tools: Move linux/kernel.h to tools/include Wang Nan
@ 2015-05-27 13:03   ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 62+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-27 13:03 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, namhyung, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama

Em Wed, May 27, 2015 at 05:19:37AM +0000, Wang Nan escreveu:
> This patch moves kernel.h from tools/perf/util/include/linux/kernel.h
> to tools/include/linux/kernel.h to enable other libraries use macros in
> it, like libbpf which will be introduced by further patches.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> ---
>  tools/{perf/util => }/include/linux/kernel.h | 0
>  1 file changed, 0 insertions(+), 0 deletions(-)
>  rename tools/{perf/util => }/include/linux/kernel.h (100%)
> 
> diff --git a/tools/perf/util/include/linux/kernel.h b/tools/include/linux/kernel.h
> similarity index 100%
> rename from tools/perf/util/include/linux/kernel.h
> rename to tools/include/linux/kernel.h

Thanks, applied and now testing it thoroughly with:

 $ make -C tools/perf build-test

Please use the above command when doing things that touches a lot of
stuff, as even in this seemingly simple case we may, for instance, end
up using the kernel's kernel.h directly and miss something we may have
on tools's (by now) kernel.h.

Ah, using 'perf test', as root, from time to time, also is highly
encouraged :-)

Thanks,

- Arnaldo

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 03/29] perf tools: Move linux/{list.h,poison.h} to tools/include
  2015-05-27  5:19 ` [RFC PATCH v4 03/29] perf tools: Move linux/{list.h,poison.h} " Wang Nan
@ 2015-05-27 13:15   ` Arnaldo Carvalho de Melo
  2015-05-27 13:21     ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 62+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-27 13:15 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, namhyung, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama

Em Wed, May 27, 2015 at 05:19:38AM +0000, Wang Nan escreveu:
> This patch moves list.h from tools/perf/util/include/linux/list.h
> to tools/include/linux/list.h to enable other libraries use macros in
> it, like libbpf which will be introduced by further patches. Since
> list.h depend on poison.h, poison.h is also moved.
 
> Both file use relative path, so one '..' is removed for each header
> to make them suit for new directory.

I'll apply this, but when doing these moves, one has to worry that these
build targets continue working:

[acme@ssdandy linux]$ make help | grep perf
  perf-tar-src-pkg    - Build perf-4.1.0-rc2.tar source tarball
  perf-targz-src-pkg  - Build perf-4.1.0-rc2.tar.gz source tarball
  perf-tarbz2-src-pkg - Build perf-4.1.0-rc2.tar.bz2 source tarball
  perf-tarxz-src-pkg  - Build perf-4.1.0-rc2.tar.xz source tarball
[acme@ssdandy linux]$ 

To explain what they are for, here is how they are used:

[acme@ssdandy linux]$ ls -la *.gz
ls: cannot access *.gz: No such file or directory
[acme@ssdandy linux]$ make perf-targz-src-pkg
  TAR
[acme@ssdandy linux]$ ls -la *.gz
-rw-rw-r--. 1 acme acme 1014070 May 27 10:07 perf-4.1.0-rc2.tar.gz
[acme@ssdandy linux]$ mkdir -p /tmp/on-some-other-machine-we-do/
[acme@ssdandy linux]$ mv perf-4.1.0-rc2.tar.gz /tmp/on-some-other-machine-we-do/
[acme@ssdandy linux]$ cd /tmp/on-some-other-machine-we-do/
[acme@ssdandy on-some-other-machine-we-do]$ tar xf perf-4.1.0-rc2.tar.gz 
[acme@ssdandy on-some-other-machine-we-do]$ ls
perf-4.1.0-rc2  perf-4.1.0-rc2.tar.gz
[acme@ssdandy on-some-other-machine-we-do]$ cd perf-4.1.0-rc2/
[acme@ssdandy perf-4.1.0-rc2]$ ls
arch  HEAD  include  lib  PERF-VERSION-FILE  tools
[acme@ssdandy perf-4.1.0-rc2]$ make -C tools/perf
make: Entering directory `/tmp/on-some-other-machine-we-do/perf-4.1.0-rc2/tools/perf'
  BUILD:   Doing 'make -j8' parallel build

Auto-detecting system features:
...                         dwarf: [ on  ]
...                         glibc: [ on  ]
...                          gtk2: [ on  ]
...                      libaudit: [ on  ]
...                        libbfd: [ on  ]
...                        libelf: [ on  ]
...                       libnuma: [ on  ]
...                       libperl: [ on  ]
...                     libpython: [ on  ]
...                      libslang: [ on  ]
...                     libunwind: [ on  ]
...            libdw-dwarf-unwind: [ on  ]
...                          zlib: [ on  ]
...                          lzma: [ on  ]

  CC       util/abspath.o
  CC       arch/common.o
  CC       ui/setup.o
  CC       fs/fs.o
  CC       event-parse.o
  PERF_VERSION = 4.1.rc2.g6bbda4
  GEN      common-cmds.h
  CC       fd/array.o
  CC       ui/gtk/browser.o
In file included from /usr/include/linux/kernel.h:4:0,
                 from util/util.h:73,
                 from util/cache.h:5,
                 from util/abspath.c:1:
/usr/include/linux/sysinfo.h:8:2: error: unknown type name ‘__kernel_long_t’
  __kernel_long_t uptime;  /* Seconds since boot */
  ^
/usr/include/linux/sysinfo.h:9:2: error: unknown type name ‘__kernel_ulong_t’
  __kernel_ulong_t loads[3]; /* 1, 5, and 15 minute load averages */
  ^
/usr/include/linux/sysinfo.h:10:2: error: unknown type name ‘__kernel_ulong_t’
  __kernel_ulong_t totalram; /* Total usable main memory size */

<BIG, BIG SNIP>
                                                                                                                                                    ^
cc1: all warnings being treated as errors
make[3]: *** [ui/gtk/hists.o] Error 1
make[2]: *** [ui/gtk] Error 2
make[1]: *** [gtk-in.o] Error 2
  LD       libtraceevent-in.o
  LD       plugin_scsi-in.o
  LINK     libtraceevent.a
  LINK     plugin_scsi.so
  LD       plugin_xen-in.o
  LINK     plugin_xen.so
make: *** [all] Error 2
make: Leaving directory `/tmp/on-some-other-machine-we-do/perf-4.1.0-rc2/tools/perf'
[acme@ssdandy perf-4.1.0-rc2]$ 

========================================================================

This is because:

[acme@ssdandy perf-4.1.0-rc2]$ ls -la tools/include/linux/kernel.h
ls: cannot access tools/include/linux/kernel.h: No such file or directory

You forgot to add this file to tools/perf/MANIFEST, that which effect would
be equivalent to:

[acme@ssdandy perf-4.1.0-rc2]$ cp ~acme/git/linux/tools/include/linux/kernel.h tools/include/linux/kernel.h
[acme@ssdandy perf-4.1.0-rc2]$ make -C tools/perf
make: Entering directory `/tmp/on-some-other-machine-we-do/perf-4.1.0-rc2/tools/perf'
  BUILD:   Doing 'make -j8' parallel build
  CC       arch/common.o
  CC       util/abspath.o
  CC       ui/gtk/browser.o
  CC       util/alias.o

<SNIP>

  LD       util/scripting-engines/libperf-in.o
  LD       util/libperf-in.o
  LD       libperf-in.o
  AR       libperf.a
  LINK     perf
  LINK     libperf-gtk.so
make: Leaving directory `/tmp/on-some-other-machine-we-do/perf-4.1.0-rc2/tools/perf'
[acme@ssdandy perf-4.1.0-rc2]$
[acme@ssdandy perf-4.1.0-rc2]$ tools/perf/perf --version
perf version 4.1.rc2.g6bbda4
[acme@ssdandy perf-4.1.0-rc2]$ ls -la tools/perf/perf
-rwxrwxr-x. 1 acme acme 11495170 May 27 10:12 tools/perf/perf
[acme@ssdandy perf-4.1.0-rc2]$ strip tools/perf/perf
[acme@ssdandy perf-4.1.0-rc2]$ ls -la tools/perf/perf
-rwxrwxr-x. 1 acme acme 2441888 May 27 10:13 tools/perf/perf
[acme@ssdandy perf-4.1.0-rc2]$

========================================================================

This, BTW, would have been caught if you had run:

  make -C tools/perf build-test

One of the last tests will do this packaging and building, alerting you that
something is missing.

I am doing this for the two patches in this series that moves things to tools,

Regards,

- Arnaldo
 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> ---
>  tools/{perf/util => }/include/linux/list.h | 6 +++---
>  tools/include/linux/poison.h               | 1 +
>  tools/perf/util/include/linux/poison.h     | 1 -
>  3 files changed, 4 insertions(+), 4 deletions(-)
>  rename tools/{perf/util => }/include/linux/list.h (90%)
>  create mode 100644 tools/include/linux/poison.h
>  delete mode 100644 tools/perf/util/include/linux/poison.h
> 
> diff --git a/tools/perf/util/include/linux/list.h b/tools/include/linux/list.h
> similarity index 90%
> rename from tools/perf/util/include/linux/list.h
> rename to tools/include/linux/list.h
> index 76ddbc7..76b014c 100644
> --- a/tools/perf/util/include/linux/list.h
> +++ b/tools/include/linux/list.h
> @@ -1,10 +1,10 @@
>  #include <linux/kernel.h>
>  #include <linux/types.h>
>  
> -#include "../../../../include/linux/list.h"
> +#include "../../../include/linux/list.h"
>  
> -#ifndef PERF_LIST_H
> -#define PERF_LIST_H
> +#ifndef TOOLS_LIST_H
> +#define TOOLS_LIST_H
>  /**
>   * list_del_range - deletes range of entries from list.
>   * @begin: first element in the range to delete from the list.
> diff --git a/tools/include/linux/poison.h b/tools/include/linux/poison.h
> new file mode 100644
> index 0000000..0c27bdf
> --- /dev/null
> +++ b/tools/include/linux/poison.h
> @@ -0,0 +1 @@
> +#include "../../../include/linux/poison.h"
> diff --git a/tools/perf/util/include/linux/poison.h b/tools/perf/util/include/linux/poison.h
> deleted file mode 100644
> index fef6dbc..0000000
> --- a/tools/perf/util/include/linux/poison.h
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include "../../../../include/linux/poison.h"
> -- 
> 1.8.3.4

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 03/29] perf tools: Move linux/{list.h,poison.h} to tools/include
  2015-05-27 13:15   ` Arnaldo Carvalho de Melo
@ 2015-05-27 13:21     ` Arnaldo Carvalho de Melo
  2015-05-27 15:30       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 62+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-27 13:21 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, namhyung, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama

Em Wed, May 27, 2015 at 10:15:12AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Wed, May 27, 2015 at 05:19:38AM +0000, Wang Nan escreveu:
> > This patch moves list.h from tools/perf/util/include/linux/list.h
> > to tools/include/linux/list.h to enable other libraries use macros in

> I'll apply this, but when doing these moves, one has to worry that these
> build targets continue working:
 
> [acme@ssdandy linux]$ make help | grep perf
>   perf-tar-src-pkg    - Build perf-4.1.0-rc2.tar source tarball
>   perf-targz-src-pkg  - Build perf-4.1.0-rc2.tar.gz source tarball

<SNIP>
 
> This, BTW, would have been caught if you had run:
> 
>   make -C tools/perf build-test
> 
> One of the last tests will do this packaging and building, alerting you that
> something is missing.
> 
> I am doing this for the two patches in this series that moves things to tools,

So, to summarize this further, and to run just this 'tarpkg' test, to speed up
testing for this specific case:

[acme@ssdandy linux]$ vim tools/perf/MANIFEST 
[acme@ssdandy linux]$ make -C tools/perf -f tests/make tarpkg
make: Entering directory `/home/acme/git/linux/tools/perf'
- tarpkg: ./tests/perf-targz-src-pkg .
make: Leaving directory `/home/acme/git/linux/tools/perf'
[acme@ssdandy linux]$ echo $?
0
[acme@ssdandy linux]$ git diff
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index a83cf75164e1..fce4a47347aa 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -40,6 +40,7 @@ tools/include/linux/bitops.h
 tools/include/linux/compiler.h
 tools/include/linux/export.h
 tools/include/linux/hash.h
+tools/include/linux/kernel.h
 tools/include/linux/log2.h
 tools/include/linux/types.h
 include/asm-generic/bitops/arch_hweight.h
[acme@ssdandy linux]$ git commit -a --amend

- Arnaldo

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 03/29] perf tools: Move linux/{list.h,poison.h} to tools/include
  2015-05-27 13:21     ` Arnaldo Carvalho de Melo
@ 2015-05-27 15:30       ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 62+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-27 15:30 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, namhyung, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama

Em Wed, May 27, 2015 at 10:21:09AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Wed, May 27, 2015 at 10:15:12AM -0300, Arnaldo Carvalho de Melo escreveu:
> > Em Wed, May 27, 2015 at 05:19:38AM +0000, Wang Nan escreveu:
> > > This patch moves list.h from tools/perf/util/include/linux/list.h
> > > to tools/include/linux/list.h to enable other libraries use macros in
> 
> > I'll apply this, but when doing these moves, one has to worry that these
> > build targets continue working:
>  
> > [acme@ssdandy linux]$ make help | grep perf
> >   perf-tar-src-pkg    - Build perf-4.1.0-rc2.tar source tarball
> >   perf-targz-src-pkg  - Build perf-4.1.0-rc2.tar.gz source tarball
> 
> <SNIP>
>  
> > This, BTW, would have been caught if you had run:
> > 
> >   make -C tools/perf build-test
> > 
> > One of the last tests will do this packaging and building, alerting you that
> > something is missing.
> > 
> > I am doing this for the two patches in this series that moves things to tools,
> 
> So, to summarize this further, and to run just this 'tarpkg' test, to speed up
> testing for this specific case:

And it explodes on RHEL6.6, I'll have to test this further...

  MKDIR    /tmp/build/perf/util/
  CC       /tmp/build/perf/util/values.o
In file included from
/home/acme/git/linux/include/uapi/linux/kernel.h:4,
                 from util/util.h:73,
                 from util/values.c:3:
/home/acme/git/linux/include/uapi/linux/sysinfo.h:8: error: expected
specifier-qualifier-list before ‘__kernel_long_t’
cc1: warnings being treated as errors
In file included from util/values.c:3:
util/util.h: In function ‘path__join’:
util/util.h:306: error: implicit declaration of function ‘scnprintf’
util/util.h:306: error: nested extern declaration of ‘scnprintf’
make[3]: *** [/tmp/build/perf/util/values.o] Error 1
make[2]: *** [util] Error 2
make[1]: *** [/tmp/build/perf/libperf-in.o] Error 2
make[1]: *** Waiting for unfinished jobs....
  PERF_VERSION = 4.1.rc2.ga82d24e
make: *** [install-bin] Error 2
make: Leaving directory `/home/acme/git/linux/tools/perf'
[acme@sandy linux]$ 


- Arnaldo

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 01/29] tools: Add __aligned_u64 to types.h
  2015-05-27 13:00   ` Arnaldo Carvalho de Melo
@ 2015-05-28  0:28     ` Wangnan (F)
  2015-05-28  0:31       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 62+ messages in thread
From: Wangnan (F) @ 2015-05-28  0:28 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: paulus, a.p.zijlstra, mingo, namhyung, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama



On 2015/5/27 21:00, Arnaldo Carvalho de Melo wrote:
> Em Wed, May 27, 2015 at 05:19:36AM +0000, Wang Nan escreveu:
>> Following patches will introduce linux/bpf.h to a new libbpf library,
>> which requires definition of __aligned_u64. This patch add it to the
>> common types.h for tools.
> This was already merged, see:
>
> http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/log/tools?h=perf/core
>
> More specifically:
>
> http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/commit/tools?h=perf/core&id=70ba6b8f975bcff56e180e2c7550d2302fcbf923
>
> So you can drop it from your patchset.
>
> BTW, where are you basing your work?
>
> If you do it over tip/perf/core you may find some of the trivial stuff
> being added there, like this one.
>   
> - Arnaldo

I base my work on v4.1-rc3. I tried tip/perf/core but there are 
confliction and some trival
problems (patch 'perf probe: Load map before glob matching' is found 
during rebasing), and
that branch changes quicker than mainline. If you and others are 
satisfied with the basic
idea of v4, I'd like to rebase v5 on tip/perf/core.

Thank you.

>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
>> ---
>>   tools/include/linux/types.h | 5 +++++
>>   1 file changed, 5 insertions(+)
>>
>> diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h
>> index b5cf25e..10a2cdc 100644
>> --- a/tools/include/linux/types.h
>> +++ b/tools/include/linux/types.h
>> @@ -60,6 +60,11 @@ typedef __u32 __bitwise __be32;
>>   typedef __u64 __bitwise __le64;
>>   typedef __u64 __bitwise __be64;
>>   
>> +/* Taken from uapi/linux/types.h. Required by linux/bpf.h */
>> +#ifndef __aligned_u64
>> +# define __aligned_u64 __u64 __attribute__((aligned(8)))
>> +#endif
>> +
>>   struct list_head {
>>   	struct list_head *next, *prev;
>>   };
>> -- 
>> 1.8.3.4



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 01/29] tools: Add __aligned_u64 to types.h
  2015-05-28  0:28     ` Wangnan (F)
@ 2015-05-28  0:31       ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 62+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-28  0:31 UTC (permalink / raw)
  To: Wangnan (F)
  Cc: paulus, a.p.zijlstra, mingo, namhyung, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama

Em Thu, May 28, 2015 at 08:28:07AM +0800, Wangnan (F) escreveu:
> 
> 
> On 2015/5/27 21:00, Arnaldo Carvalho de Melo wrote:
> >Em Wed, May 27, 2015 at 05:19:36AM +0000, Wang Nan escreveu:
> >>Following patches will introduce linux/bpf.h to a new libbpf library,
> >>which requires definition of __aligned_u64. This patch add it to the
> >>common types.h for tools.
> >This was already merged, see:
> >
> >http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/log/tools?h=perf/core
> >
> >More specifically:
> >
> >http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/commit/tools?h=perf/core&id=70ba6b8f975bcff56e180e2c7550d2302fcbf923
> >
> >So you can drop it from your patchset.
> >
> >BTW, where are you basing your work?
> >
> >If you do it over tip/perf/core you may find some of the trivial stuff
> >being added there, like this one.
> >- Arnaldo
 
> I base my work on v4.1-rc3. I tried tip/perf/core but there are
> confliction and some trival problems (patch 'perf probe: Load map
> before glob matching' is found during rebasing), and that branch
> changes quicker than mainline. If you and others are satisfied with
> the basic idea of v4, I'd like to rebase v5 on tip/perf/core.


I'll try to take a hard look at it tomorrow and will let you know.

- Arnaldo
 
> Thank you.
> 
> >>Signed-off-by: Wang Nan <wangnan0@huawei.com>
> >>---
> >>  tools/include/linux/types.h | 5 +++++
> >>  1 file changed, 5 insertions(+)
> >>
> >>diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h
> >>index b5cf25e..10a2cdc 100644
> >>--- a/tools/include/linux/types.h
> >>+++ b/tools/include/linux/types.h
> >>@@ -60,6 +60,11 @@ typedef __u32 __bitwise __be32;
> >>  typedef __u64 __bitwise __le64;
> >>  typedef __u64 __bitwise __be64;
> >>+/* Taken from uapi/linux/types.h. Required by linux/bpf.h */
> >>+#ifndef __aligned_u64
> >>+# define __aligned_u64 __u64 __attribute__((aligned(8)))
> >>+#endif
> >>+
> >>  struct list_head {
> >>  	struct list_head *next, *prev;
> >>  };
> >>-- 
> >>1.8.3.4
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 06/29] bpf tools: Open eBPF object file and do basic validation
  2015-05-27  5:19 ` [RFC PATCH v4 06/29] bpf tools: Open eBPF object file and do basic validation Wang Nan
@ 2015-05-28  1:44   ` Alexei Starovoitov
  0 siblings, 0 replies; 62+ messages in thread
From: Alexei Starovoitov @ 2015-05-28  1:44 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama

On Wed, May 27, 2015 at 05:19:41AM +0000, Wang Nan wrote:
> This patch defines basic interface of libbpf. 'struct bpf_object' will
> be the handler of each object file. Its internal structure is hide to
> user. eBPF object files are compiled by LLVM as ELF format. In this
> patch, libelf is used to open those files, read EHDR and do basic
> validation according to e_type and e_machine.
> 
> All elf related staffs are grouped together and reside in efile field of
> 'struct bpf_object'. bpf_object__elf_finish() is introduced to clear it.
> 
> After all eBPF programs in an object file are loaded, related ELF
> information is useless. Close the object file and free those memory.
> 
> zfree() and zclose() are introduced to ensure setting NULL pointers and
> negative file descriptors after resources are released.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>

the __ notation actually looks good in this context.
Acked-by: Alexei Starovoitov <ast@plumgrid.com>

btw, you didn't cc me on this set, luckily I found it on lkml.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 07/29] bpf tools: Check endianess and make libbpf fail early
  2015-05-27  5:19 ` [RFC PATCH v4 07/29] bpf tools: Check endianess and make libbpf fail early Wang Nan
@ 2015-05-28  1:45   ` Alexei Starovoitov
  0 siblings, 0 replies; 62+ messages in thread
From: Alexei Starovoitov @ 2015-05-28  1:45 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama

On Wed, May 27, 2015 at 05:19:42AM +0000, Wang Nan wrote:
> Check endianess according to EHDR. Code is taken from
> tools/perf/util/symbol-elf.c.
> 
> Libbpf doesn't magically convert missmatched endianess. See discussion
> on https://lkml.org/lkml/2015/5/18/650 that, even if we swap
> eBPF instructions to correct byte order, we are unable to deal with
> endianess in code logical generated by LLVM.
> 
> Therefore, libbpf should simply reject missmatched ELF object, and let
> LLVM to create good code.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>

lgtm
Acked-by: Alexei Starovoitov <ast@plumgrid.com>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 08/29] bpf tools: Iterate over ELF sections to collect information
  2015-05-27  5:19 ` [RFC PATCH v4 08/29] bpf tools: Iterate over ELF sections to collect information Wang Nan
@ 2015-05-28  1:46   ` Alexei Starovoitov
  0 siblings, 0 replies; 62+ messages in thread
From: Alexei Starovoitov @ 2015-05-28  1:46 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama

On Wed, May 27, 2015 at 05:19:43AM +0000, Wang Nan wrote:
> bpf_obj_elf_collect() is introduced to iterate over each elf sections
> to collection informations in eBPF object files. This function will
> futher enhanced to collect license, kernel version, programs, configs
> and map information.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>

Acked-by: Alexei Starovoitov <ast@plumgrid.com>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 09/29] bpf tools: Collect version and license from ELF sections
  2015-05-27  5:19 ` [RFC PATCH v4 09/29] bpf tools: Collect version and license from ELF sections Wang Nan
@ 2015-05-28  1:48   ` Alexei Starovoitov
  2015-05-28  3:34     ` Wangnan (F)
  0 siblings, 1 reply; 62+ messages in thread
From: Alexei Starovoitov @ 2015-05-28  1:48 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama

On Wed, May 27, 2015 at 05:19:44AM +0000, Wang Nan wrote:
> Expand bpf_obj_elf_collect() to collect license and kernel version
> information in eBPF object file. eBPF object file should have a section
> named 'license', which contains a string. It should also have a section
> named 'version', contains a u32 LINUX_VERSION_CODE.
> 
> bpf_obj_validate() is introduced to validate object file after loaded.
> Currently it only check existance of 'version' section.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> ---
...
> +static int
> +bpf_object__init_kversion(struct bpf_object *obj,
> +			  void *data, size_t size)
> +{
> +	u32 kver;
> +	if (size < sizeof(kver)) {

shouldn't it be '!=' ?

> +		pr_warning("invalid kver section in %s\n", obj->path);
> +		return -EINVAL;
> +	}
> +	memcpy(&kver, data, sizeof(kver));
> +	obj->kern_version = kver;
> +	pr_debug("kernel version of %s is %x\n", obj->path,
> +		 obj->kern_version);
> +	return 0;
> +}
> +

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-05-27  5:19 ` [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section Wang Nan
@ 2015-05-28  1:53   ` Alexei Starovoitov
  2015-05-28  2:03     ` Wangnan (F)
  0 siblings, 1 reply; 62+ messages in thread
From: Alexei Starovoitov @ 2015-05-28  1:53 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama

On Wed, May 27, 2015 at 05:19:45AM +0000, Wang Nan wrote:
> If maps are used by eBPF programs, corresponding object file(s) should
> contain a section named 'map'. Which contains map definitions. This
> patch copies the data of the whole section. Map data parsing should be
> acted just before map loading.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> ---
...
> +static int
> +bpf_object__init_maps(struct bpf_object *obj, void *data,
> +		      size_t size)
> +{
> +	if (size == 0) {
> +		pr_debug("%s doesn't need map definition\n",
> +			 obj->path);
> +		return 0;
> +	}
> +
> +	obj->maps_buf = malloc(size);
> +	if (!obj->maps_buf) {
> +		pr_warning("malloc maps failed: %s\n", obj->path);
> +		return -ENOMEM;
> +	}
> +
> +	obj->maps_buf_sz = size;
> +	memcpy(obj->maps_buf, data, size);

why copy it? To create maps and apply fixups to instructions
relo sections are needed anyway, so elf has to be open while
this section is being processed. So why copy?


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 15/29] bpf tools: Add bpf.c/h for common bpf operations
  2015-05-27  5:19 ` [RFC PATCH v4 15/29] bpf tools: Add bpf.c/h for common bpf operations Wang Nan
@ 2015-05-28  1:55   ` Alexei Starovoitov
  2015-05-29 14:44   ` Namhyung Kim
  1 sibling, 0 replies; 62+ messages in thread
From: Alexei Starovoitov @ 2015-05-28  1:55 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama

On Wed, May 27, 2015 at 05:19:50AM +0000, Wang Nan wrote:
> This patch introduces bpf.c and bpf.h, which hold common functions
> issuing bpf syscall. The goal of these two files is to hide syscall
> completly from user.  Note that bpf.c and bpf.h only deal with kernel
> interface. Things like structure of 'map' section in the ELF object is
> not cared by of bpf.[ch].
> 
> We first introduce bpf_create_map().
> 
> Note that, since functions in bpf.[ch] are wrapper of sys_bpf, they
> don't use OO style naming.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>

Acked-by: Alexei Starovoitov <ast@plumgrid.com>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 16/29] bpf tools: Create eBPF maps defined in an object file
  2015-05-27  5:19 ` [RFC PATCH v4 16/29] bpf tools: Create eBPF maps defined in an object file Wang Nan
@ 2015-05-28  1:57   ` Alexei Starovoitov
  0 siblings, 0 replies; 62+ messages in thread
From: Alexei Starovoitov @ 2015-05-28  1:57 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama

On Wed, May 27, 2015 at 05:19:51AM +0000, Wang Nan wrote:
> This patch creates maps based on 'map' section in object file using
> bpf_create_map(), and store the fds into an array in
> 'struct bpf_object'. Since the byte order of the object may differ
> from the host, swap map definition before processing.

obsolete commit log?
The code doesn't do byteswap and it shouldn't.
The other patch already checked for matching endiannes.

> This is the first patch in 'loading' phase. Previous patches parse ELF
> object file and create needed data structure, but doesn't play with
> kernel. They belong to 'opening' phase.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-05-28  1:53   ` Alexei Starovoitov
@ 2015-05-28  2:03     ` Wangnan (F)
  2015-05-28  2:28       ` Alexei Starovoitov
  0 siblings, 1 reply; 62+ messages in thread
From: Wangnan (F) @ 2015-05-28  2:03 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama



On 2015/5/28 9:53, Alexei Starovoitov wrote:
> On Wed, May 27, 2015 at 05:19:45AM +0000, Wang Nan wrote:
>> If maps are used by eBPF programs, corresponding object file(s) should
>> contain a section named 'map'. Which contains map definitions. This
>> patch copies the data of the whole section. Map data parsing should be
>> acted just before map loading.
>>
>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
>> ---
> ...
>> +static int
>> +bpf_object__init_maps(struct bpf_object *obj, void *data,
>> +		      size_t size)
>> +{
>> +	if (size == 0) {
>> +		pr_debug("%s doesn't need map definition\n",
>> +			 obj->path);
>> +		return 0;
>> +	}
>> +
>> +	obj->maps_buf = malloc(size);
>> +	if (!obj->maps_buf) {
>> +		pr_warning("malloc maps failed: %s\n", obj->path);
>> +		return -ENOMEM;
>> +	}
>> +
>> +	obj->maps_buf_sz = size;
>> +	memcpy(obj->maps_buf, data, size);
> why copy it? To create maps and apply fixups to instructions
> relo sections are needed anyway, so elf has to be open while
> this section is being processed. So why copy?
>

When creating maps, ELF file has been closed.

I divide libelf info two phases: opening and loading. ELF file is closed
at the end of opening phase. I think some caller need 'opening' phase only.
For example, checking metadata in an eBPF object file. In this case, we 
don't
need create map file descriptors.

Sorry for not cc you.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 18/29] bpf tools: Introduce bpf_load_program() to bpf.c
  2015-05-27  5:19 ` [RFC PATCH v4 18/29] bpf tools: Introduce bpf_load_program() to bpf.c Wang Nan
@ 2015-05-28  2:14   ` Alexei Starovoitov
  0 siblings, 0 replies; 62+ messages in thread
From: Alexei Starovoitov @ 2015-05-28  2:14 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama

On Wed, May 27, 2015 at 05:19:53AM +0000, Wang Nan wrote:
> bpf_load_program() can be used to load bpf program into kernel. To make
> loading faster, first try to load without logbuf. Try again with logbuf
> if the first try failed.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>

Acked-by: Alexei Starovoitov <ast@plumgrid.com>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-05-28  2:03     ` Wangnan (F)
@ 2015-05-28  2:28       ` Alexei Starovoitov
  2015-05-28  3:09         ` Wangnan (F)
  0 siblings, 1 reply; 62+ messages in thread
From: Alexei Starovoitov @ 2015-05-28  2:28 UTC (permalink / raw)
  To: Wangnan (F)
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama

On Thu, May 28, 2015 at 10:03:04AM +0800, Wangnan (F) wrote:
> 
> 
> On 2015/5/28 9:53, Alexei Starovoitov wrote:
> >On Wed, May 27, 2015 at 05:19:45AM +0000, Wang Nan wrote:
> >>If maps are used by eBPF programs, corresponding object file(s) should
> >>contain a section named 'map'. Which contains map definitions. This
> >>patch copies the data of the whole section. Map data parsing should be
> >>acted just before map loading.
> >>
> >>Signed-off-by: Wang Nan <wangnan0@huawei.com>
> >>---
> >...
> >>+static int
> >>+bpf_object__init_maps(struct bpf_object *obj, void *data,
> >>+		      size_t size)
> >>+{
> >>+	if (size == 0) {
> >>+		pr_debug("%s doesn't need map definition\n",
> >>+			 obj->path);
> >>+		return 0;
> >>+	}
> >>+
> >>+	obj->maps_buf = malloc(size);
> >>+	if (!obj->maps_buf) {
> >>+		pr_warning("malloc maps failed: %s\n", obj->path);
> >>+		return -ENOMEM;
> >>+	}
> >>+
> >>+	obj->maps_buf_sz = size;
> >>+	memcpy(obj->maps_buf, data, size);
> >why copy it? To create maps and apply fixups to instructions
> >relo sections are needed anyway, so elf has to be open while
> >this section is being processed. So why copy?
> >
> 
> When creating maps, ELF file has been closed.
> 
> I divide libelf info two phases: opening and loading. ELF file is closed
> at the end of opening phase. I think some caller need 'opening' phase only.
> For example, checking metadata in an eBPF object file. In this case, we
> don't
> need create map file descriptors.

loading elf into memory, parsing it, copying map, prog, relo sections
just to check metadata? That doesn't sound like real use case.
imo it's cleaner to remember where maps and relocations are in a loaded elf,
then create maps, patch copied progs and release all elf.
This elfs are all very small, so we're not talking about large memory savings,
but still.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-05-28  2:28       ` Alexei Starovoitov
@ 2015-05-28  3:09         ` Wangnan (F)
  2015-05-28  6:09           ` Alexei Starovoitov
  0 siblings, 1 reply; 62+ messages in thread
From: Wangnan (F) @ 2015-05-28  3:09 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama, xiakaixu 00238161



On 2015/5/28 10:28, Alexei Starovoitov wrote:
> On Thu, May 28, 2015 at 10:03:04AM +0800, Wangnan (F) wrote:
>>
>> On 2015/5/28 9:53, Alexei Starovoitov wrote:
>>> On Wed, May 27, 2015 at 05:19:45AM +0000, Wang Nan wrote:
>>>> If maps are used by eBPF programs, corresponding object file(s) should
>>>> contain a section named 'map'. Which contains map definitions. This
>>>> patch copies the data of the whole section. Map data parsing should be
>>>> acted just before map loading.
>>>>
>>>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
>>>> ---
>>> ...
>>>> +static int
>>>> +bpf_object__init_maps(struct bpf_object *obj, void *data,
>>>> +		      size_t size)
>>>> +{
>>>> +	if (size == 0) {
>>>> +		pr_debug("%s doesn't need map definition\n",
>>>> +			 obj->path);
>>>> +		return 0;
>>>> +	}
>>>> +
>>>> +	obj->maps_buf = malloc(size);
>>>> +	if (!obj->maps_buf) {
>>>> +		pr_warning("malloc maps failed: %s\n", obj->path);
>>>> +		return -ENOMEM;
>>>> +	}
>>>> +
>>>> +	obj->maps_buf_sz = size;
>>>> +	memcpy(obj->maps_buf, data, size);
>>> why copy it? To create maps and apply fixups to instructions
>>> relo sections are needed anyway, so elf has to be open while
>>> this section is being processed. So why copy?
>>>
>> When creating maps, ELF file has been closed.
>>
>> I divide libelf info two phases: opening and loading. ELF file is closed
>> at the end of opening phase. I think some caller need 'opening' phase only.
>> For example, checking metadata in an eBPF object file. In this case, we
>> don't
>> need create map file descriptors.
> loading elf into memory, parsing it, copying map, prog, relo sections
> just to check metadata? That doesn't sound like real use case.
> imo it's cleaner to remember where maps and relocations are in a loaded elf,
> then create maps, patch copied progs and release all elf.
> This elfs are all very small, so we're not talking about large memory savings,
> but still.
>

So do you suggest me to create maps in opening phase?

In bpf_object__open:

struct bpf_object *bpf_object__open(const char *path)
{
        ....
        if (bpf_object__elf_init(obj))
                goto out;

        /* Real useful things put here */
        ....
        /* Here we collect map information */
        if (bpf_object__elf_collect(obj))
                goto out;
        ....
        /* And ELF file is closed here */
        bpf_object__elf_finish(obj);
        ....
}

You can see that, after bpf_object__open() return we won't have chance
to access map data. Therefore we must create maps in bpf_object__open().

However this breaks a law in current design that opening phase doesn't
talk to kernel with sys_bpf() at all. All related staff is done in loading
phase. This principle ensures that in every systems, no matter it support
sys_bpf() or not, can read eBPF object without failure.

In fact I didn't separate opening and loading when I start working on 
libbpf.
However I soon found inconvenience that:
   1. The uniform design doesn't allow users to adjust things before 
doing real work;
   2. In my development environment I write code on a server without 
sys_bpf() support,
      the uniform design prevent me to test my opening phase code. I 
have to test it
      in QEMU.

In addition, this copying gives libbpf an ability that it can open once and
load - unload - load - unload many times without reopening and reparsing the
ELF file.

Moreover, we are planning to introduce hardware PMU to eBPF in the way 
like maps,
to give eBPF programs the ability to access hardware PMU counter. I 
haven't think
it thoroughly so I didn't discuss it with you and others. I think it 
should be
something like:

struct bpf_pmu {
   /* attr of the hardware PMU which will be passed to perf_event_open 
to create an FD */
};

SEC("hw_pmu")
struct bpf_pmu cache_misses = {
    ...
};

SEC("lock_page=lock_page")
int lock_page_hook(struct pt_regs *ctx)
{
     ...
     counter = bpf_read_pmu_counter(&cache_misses);
     ...
}

(My colleague Xia Kaixu is working on it. I append him to the CC list).
Creating that PMU FDs may require perf to adjust more things than 
programs and maps.
I believe that we shouldn't let libbpf to do its own without help from 
caller. Therefore
the separation of opening and loading should be required.

What do you think?

Thank you.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 09/29] bpf tools: Collect version and license from ELF sections
  2015-05-28  1:48   ` Alexei Starovoitov
@ 2015-05-28  3:34     ` Wangnan (F)
  2015-05-28  5:51       ` Alexei Starovoitov
  0 siblings, 1 reply; 62+ messages in thread
From: Wangnan (F) @ 2015-05-28  3:34 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama



On 2015/5/28 9:48, Alexei Starovoitov wrote:
> On Wed, May 27, 2015 at 05:19:44AM +0000, Wang Nan wrote:
>> Expand bpf_obj_elf_collect() to collect license and kernel version
>> information in eBPF object file. eBPF object file should have a section
>> named 'license', which contains a string. It should also have a section
>> named 'version', contains a u32 LINUX_VERSION_CODE.
>>
>> bpf_obj_validate() is introduced to validate object file after loaded.
>> Currently it only check existance of 'version' section.
>>
>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
>> ---
> ...
>> +static int
>> +bpf_object__init_kversion(struct bpf_object *obj,
>> +			  void *data, size_t size)
>> +{
>> +	u32 kver;
>> +	if (size < sizeof(kver)) {
> shouldn't it be '!=' ?

Is it possible that LLVM pads 'version' section so the size of it becomes
longer than sizeof(u32)?

Thank you.

>> +		pr_warning("invalid kver section in %s\n", obj->path);
>> +		return -EINVAL;
>> +	}
>> +	memcpy(&kver, data, sizeof(kver));
>> +	obj->kern_version = kver;
>> +	pr_debug("kernel version of %s is %x\n", obj->path,
>> +		 obj->kern_version);
>> +	return 0;
>> +}
>> +



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 09/29] bpf tools: Collect version and license from ELF sections
  2015-05-28  3:34     ` Wangnan (F)
@ 2015-05-28  5:51       ` Alexei Starovoitov
  0 siblings, 0 replies; 62+ messages in thread
From: Alexei Starovoitov @ 2015-05-28  5:51 UTC (permalink / raw)
  To: Wangnan (F)
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama

On Thu, May 28, 2015 at 11:34:37AM +0800, Wangnan (F) wrote:
> >...
> >>+static int
> >>+bpf_object__init_kversion(struct bpf_object *obj,
> >>+			  void *data, size_t size)
> >>+{
> >>+	u32 kver;
> >>+	if (size < sizeof(kver)) {
> >shouldn't it be '!=' ?
> 
> Is it possible that LLVM pads 'version' section so the size of it becomes
> longer than sizeof(u32)?

llvm will not be padding a section unless user asks for it.
Try objdump on *_kern.o


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-05-28  3:09         ` Wangnan (F)
@ 2015-05-28  6:09           ` Alexei Starovoitov
  2015-05-28  7:14             ` Wangnan (F)
  0 siblings, 1 reply; 62+ messages in thread
From: Alexei Starovoitov @ 2015-05-28  6:09 UTC (permalink / raw)
  To: Wangnan (F)
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama, xiakaixu 00238161

On Thu, May 28, 2015 at 11:09:50AM +0800, Wangnan (F) wrote:
> 
> However this breaks a law in current design that opening phase doesn't
> talk to kernel with sys_bpf() at all. All related staff is done in loading
> phase. This principle ensures that in every systems, no matter it support
> sys_bpf() or not, can read eBPF object without failure.

I see, so you want 'parse elf' and 'create maps + load programs'
to be separate phases?
Fair enough. Then please add a call to release the information
collected from elf after program loading is done.
relocations and other things are not needed at that point.

> Moreover, we are planning to introduce hardware PMU to eBPF in the way like
> maps,
> to give eBPF programs the ability to access hardware PMU counter. I haven't

that's very interesting. Please share more info when you can :)
If I understood it right, you want in-kernel bpf to do aggregation
and filtering of pmu counters ?
And computing a number of cache misses between two kprobe events?
I can see how I can use that to measure not only time
taken by syscall, but number of cache misses occurred due
to syscall. Sounds very useful!


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-05-28  6:09           ` Alexei Starovoitov
@ 2015-05-28  7:14             ` Wangnan (F)
  2015-05-29  3:35               ` Alexei Starovoitov
  0 siblings, 1 reply; 62+ messages in thread
From: Wangnan (F) @ 2015-05-28  7:14 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama, xiakaixu 00238161



On 2015/5/28 14:09, Alexei Starovoitov wrote:
> On Thu, May 28, 2015 at 11:09:50AM +0800, Wangnan (F) wrote:
>> However this breaks a law in current design that opening phase doesn't
>> talk to kernel with sys_bpf() at all. All related staff is done in loading
>> phase. This principle ensures that in every systems, no matter it support
>> sys_bpf() or not, can read eBPF object without failure.
> I see, so you want 'parse elf' and 'create maps + load programs'
> to be separate phases?
> Fair enough. Then please add a call to release the information
> collected from elf after program loading is done.
> relocations and other things are not needed at that point.

What about appending a flag into bpf_object__load() to let it know
whether to cleanup resource it taken or not? for example:

  int bpf_object__load(struct bpf_object *obj, bool clean);

then we can further wrap it by a macro:

  #define bpf_object__load_clean(o) bpf_object__load(o, true)

If 'clear' is true, after loading resources will be freed, and the same
object will be unable to reload again after unload. B doing this we can
avoid adding a new function.

>> Moreover, we are planning to introduce hardware PMU to eBPF in the way like
>> maps,
>> to give eBPF programs the ability to access hardware PMU counter. I haven't
> that's very interesting. Please share more info when you can :)
> If I understood it right, you want in-kernel bpf to do aggregation
> and filtering of pmu counters ?
> And computing a number of cache misses between two kprobe events?
> I can see how I can use that to measure not only time
> taken by syscall, but number of cache misses occurred due
> to syscall. Sounds very useful!

I'm glad to see you are also interested with it.

Of course, filtering and aggregation based on PMU counter will be 
useful, but
this is only our first goal.

You know there are many useful PMU provided by x86 and ARM64. Many 
people ask
me if there is a way to record absolute PMU counter value when sampling, so
they can measure IPC changing, cache miss rate, page faults and so on.
Currently 'perf state' is able to read PMU counter, but the cost is
relatively high.

For me, enable eBPF program to read PMU counter is the first thing need 
to be done.
The other thing is enabling eBPF programs to bring some information to 
perf sample.

Here is an example to show my idea.

I have a program which:

int main()
{
   while(1) {
     read(...);
     /* do A */
     write(...);
     /* do B */
   }
}

Then by using following script:

  SEC("enter=sys_write $outdata:u64")
  int enter_sys_write(...) {
    u64 cycles_cnt = bpf_read_pmu(&cycles_pmu);
    bpf_store_value(cycles_cnt);
    return 1;
  }

  SEC("enter=sys_read $outdata:u64")
  int enter_sys_read(...) {
    u64 cycles_cnt = bpf_read_pmu(&cycles_pmu);
    bpf_store_value(cycles_cnt);
    return 1;
  }

by 'perf script', we can check the counter of cycles at each points, 
then we are allowed
to compute the number of cycles between any two sampling points. This 
way we can compute
how many cycles taken by A and B. If instruction counter is also 
recorded, we will know
the IPC of A and B.

Above is still a casual idea. Currently I focus on bring eBPF to perf. 
This should
be the base for all other interesting stuffs. However, I'm glad to see 
people discuss
with it.

Thank you.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-05-28  7:14             ` Wangnan (F)
@ 2015-05-29  3:35               ` Alexei Starovoitov
  2015-05-29  3:59                 ` Wangnan (F)
  2015-06-01  2:12                 ` Namhyung Kim
  0 siblings, 2 replies; 62+ messages in thread
From: Alexei Starovoitov @ 2015-05-29  3:35 UTC (permalink / raw)
  To: Wangnan (F)
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama, xiakaixu 00238161

On Thu, May 28, 2015 at 03:14:44PM +0800, Wangnan (F) wrote:
> 
> 
> On 2015/5/28 14:09, Alexei Starovoitov wrote:
> >On Thu, May 28, 2015 at 11:09:50AM +0800, Wangnan (F) wrote:
> >>However this breaks a law in current design that opening phase doesn't
> >>talk to kernel with sys_bpf() at all. All related staff is done in loading
> >>phase. This principle ensures that in every systems, no matter it support
> >>sys_bpf() or not, can read eBPF object without failure.
> >I see, so you want 'parse elf' and 'create maps + load programs'
> >to be separate phases?
> >Fair enough. Then please add a call to release the information
> >collected from elf after program loading is done.
> >relocations and other things are not needed at that point.
> 
> What about appending a flag into bpf_object__load() to let it know
> whether to cleanup resource it taken or not? for example:
> 
>  int bpf_object__load(struct bpf_object *obj, bool clean);
> 
> then we can further wrap it by a macro:
> 
>  #define bpf_object__load_clean(o) bpf_object__load(o, true)
> 
> If 'clear' is true, after loading resources will be freed, and the same
> object will be unable to reload again after unload. B doing this we can
> avoid adding a new function.

imo that would be an ugly API. You only want to do that to have
one less library API function? I think it's cleaner to let user of
the library call it when necessary.
Or do cleaning unconditionally. I don't see a use case when the
same set of maps and programs would need to be loaded twice into the kernel.

> >>Moreover, we are planning to introduce hardware PMU to eBPF in the way like
> >>maps,
> >>to give eBPF programs the ability to access hardware PMU counter. I haven't
> >that's very interesting. Please share more info when you can :)
> >If I understood it right, you want in-kernel bpf to do aggregation
> >and filtering of pmu counters ?
> >And computing a number of cache misses between two kprobe events?
> >I can see how I can use that to measure not only time
> >taken by syscall, but number of cache misses occurred due
> >to syscall. Sounds very useful!
> 
> I'm glad to see you are also interested with it.
> 
> Of course, filtering and aggregation based on PMU counter will be useful,
> but
> this is only our first goal.
> 
> You know there are many useful PMU provided by x86 and ARM64. Many people
> ask
> me if there is a way to record absolute PMU counter value when sampling, so
> they can measure IPC changing, cache miss rate, page faults and so on.
> Currently 'perf state' is able to read PMU counter, but the cost is
> relatively high.
> 
> For me, enable eBPF program to read PMU counter is the first thing need to
> be done.
> The other thing is enabling eBPF programs to bring some information to perf
> sample.
> 
> Here is an example to show my idea.
> 
> I have a program which:
> 
> int main()
> {
>   while(1) {
>     read(...);
>     /* do A */
>     write(...);
>     /* do B */
>   }
> }
> 
> Then by using following script:
> 
>  SEC("enter=sys_write $outdata:u64")
>  int enter_sys_write(...) {
>    u64 cycles_cnt = bpf_read_pmu(&cycles_pmu);
>    bpf_store_value(cycles_cnt);
>    return 1;
>  }
> 
>  SEC("enter=sys_read $outdata:u64")
>  int enter_sys_read(...) {
>    u64 cycles_cnt = bpf_read_pmu(&cycles_pmu);
>    bpf_store_value(cycles_cnt);
>    return 1;
>  }
> 
> by 'perf script', we can check the counter of cycles at each points, then we
> are allowed
> to compute the number of cycles between any two sampling points. This way we
> can compute
> how many cycles taken by A and B. If instruction counter is also recorded,
> we will know
> the IPC of A and B.

Agree. That's useful. That's exactly what I meant by
"compute a number of cache misses between two kprobe events".
The overhead is less when bpf program computes the cycle and instruction
delta, computes IPC and passes only final IPC numbers to the user space.
It can even average IPC over time.
For some very frequent events it can read cycle_cnt on sys_entry_read,
then read it on sys_exit_read, compute delta and average it into the map.
User space can read the map every second or every 10 seconds and print
nice graph.
As far as 'bpf_store_value' goes... I was thinking to expose perf ring_buffer
to bpf programs, so that program can stream any data to perf that receives
it via mmap. Then you don't need this '$outdata' hack.

> Above is still a casual idea. Currently I focus on bring eBPF to perf. This
> should be the base for all other interesting stuffs.

Yes. I think this first step is almost ready.
Looking forward to your next set of patches.
Thanks!


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-05-29  3:35               ` Alexei Starovoitov
@ 2015-05-29  3:59                 ` Wangnan (F)
  2015-06-01  2:12                 ` Namhyung Kim
  1 sibling, 0 replies; 62+ messages in thread
From: Wangnan (F) @ 2015-05-29  3:59 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: paulus, a.p.zijlstra, mingo, acme, namhyung, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama, xiakaixu 00238161



On 2015/5/29 11:35, Alexei Starovoitov wrote:
> On Thu, May 28, 2015 at 03:14:44PM +0800, Wangnan (F) wrote:
>>
>> On 2015/5/28 14:09, Alexei Starovoitov wrote:
>>> On Thu, May 28, 2015 at 11:09:50AM +0800, Wangnan (F) wrote:
>>>> However this breaks a law in current design that opening phase doesn't
>>>> talk to kernel with sys_bpf() at all. All related staff is done in loading
>>>> phase. This principle ensures that in every systems, no matter it support
>>>> sys_bpf() or not, can read eBPF object without failure.
>>> I see, so you want 'parse elf' and 'create maps + load programs'
>>> to be separate phases?
>>> Fair enough. Then please add a call to release the information
>>> collected from elf after program loading is done.
>>> relocations and other things are not needed at that point.
>> What about appending a flag into bpf_object__load() to let it know
>> whether to cleanup resource it taken or not? for example:
>>
>>   int bpf_object__load(struct bpf_object *obj, bool clean);
>>
>> then we can further wrap it by a macro:
>>
>>   #define bpf_object__load_clean(o) bpf_object__load(o, true)
>>
>> If 'clear' is true, after loading resources will be freed, and the same
>> object will be unable to reload again after unload. B doing this we can
>> avoid adding a new function.
> imo that would be an ugly API. You only want to do that to have
> one less library API function? I think it's cleaner to let user of
> the library call it when necessary.
> Or do cleaning unconditionally. I don't see a use case when the
> same set of maps and programs would need to be loaded twice into the kernel.

OK. Let bpf_object__load() clean resources unconditionally.

Thank you.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 05/29] bpf tools: Allow caller to set printing function
  2015-05-27  5:19 ` [RFC PATCH v4 05/29] bpf tools: Allow caller to set printing function Wang Nan
@ 2015-05-29 13:35   ` Namhyung Kim
  0 siblings, 0 replies; 62+ messages in thread
From: Namhyung Kim @ 2015-05-29 13:35 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, acme, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama

Hi Wang,

On Wed, May 27, 2015 at 05:19:40AM +0000, Wang Nan wrote:
> By libbpf_set_print(), users of libbpf are allowed to register he/she
> own debug, info and warning printing functions. Libbpf will use those
> functions to print messages. If not provided, default info and warning
> printing functions are fprintf(stderr, ...); defailt debug printing
> is NULL.
> 
> This API is designed to be used by perf, enables it to register its own
> logging functions to make all logs uniform, instead of separated
> logging level control.
> 
> Acked-by: Alexei Starovoitov <ast@plumgrid.com>
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> ---
>  tools/lib/bpf/libbpf.c | 43 +++++++++++++++++++++++++++++++++++++++++++
>  tools/lib/bpf/libbpf.h |  4 ++++
>  2 files changed, 47 insertions(+)
> 
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index c08d6bc..49091c3 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -7,8 +7,51 @@
>   */
>  
>  #include <stdlib.h>
> +#include <stdio.h>
> +#include <stdarg.h>
> +#include <string.h>
>  #include <unistd.h>
>  #include <asm/unistd.h>
>  #include <linux/bpf.h>
>  
>  #include "libbpf.h"
> +
> +#define __printf(a, b)	__attribute__((format(printf, a, b)))
> +
> +__printf(1, 2)
> +static int __base_pr(const char *format, ...)
> +{
> +	va_list args;
> +	int err;
> +
> +	va_start(args, format);
> +	err = vfprintf(stderr, format, args);
> +	va_end(args);
> +	return err;
> +}
> +
> +static __printf(1, 2) int (*__pr_warning)(const char *format, ...) =
> +	__base_pr;
> +static __printf(1, 2) int (*__pr_info)(const char *format, ...) =
> +	__base_pr;
> +static __printf(1, 2) int (*__pr_debug)(const char *format, ...) =
> +	NULL;

What about using typedef for this.. like print_fn_t ?

Thanks,
Namhyung


> +
> +#define __pr(func, fmt, ...)	\
> +do { 				\
> +	if ((func))	\
> +		(func)("libbpf: " fmt, ##__VA_ARGS__); \
> +} while(0)
> +
> +#define pr_warning(fmt, ...)	__pr(__pr_warning, fmt, ##__VA_ARGS__)
> +#define pr_info(fmt, ...)	__pr(__pr_info, fmt, ##__VA_ARGS__)
> +#define pr_debug(fmt, ...)	__pr(__pr_debug, fmt, ##__VA_ARGS__)
> +
> +void libbpf_set_print(int (*warn)(const char *format, ...),
> +		      int (*info)(const char *format, ...),
> +		      int (*debug)(const char *format, ...))
> +{
> +	__pr_warning = warn;
> +	__pr_info = info;
> +	__pr_debug = debug;
> +}
> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index a6f46d9..430b122 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -8,4 +8,8 @@
>  #ifndef __BPF_LIBBPF_H
>  #define __BPF_LIBBPF_H
>  
> +void libbpf_set_print(int (*warn)(const char *format, ...),
> +		      int (*info)(const char *format, ...),
> +		      int (*debug)(const char *format, ...));
> +
>  #endif
> -- 
> 1.8.3.4
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 15/29] bpf tools: Add bpf.c/h for common bpf operations
  2015-05-27  5:19 ` [RFC PATCH v4 15/29] bpf tools: Add bpf.c/h for common bpf operations Wang Nan
  2015-05-28  1:55   ` Alexei Starovoitov
@ 2015-05-29 14:44   ` Namhyung Kim
  1 sibling, 0 replies; 62+ messages in thread
From: Namhyung Kim @ 2015-05-29 14:44 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, acme, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama

On Wed, May 27, 2015 at 05:19:50AM +0000, Wang Nan wrote:
> This patch introduces bpf.c and bpf.h, which hold common functions
> issuing bpf syscall. The goal of these two files is to hide syscall
> completly from user.  Note that bpf.c and bpf.h only deal with kernel
> interface. Things like structure of 'map' section in the ELF object is
> not cared by of bpf.[ch].
> 
> We first introduce bpf_create_map().
> 
> Note that, since functions in bpf.[ch] are wrapper of sys_bpf, they
> don't use OO style naming.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> ---
>  tools/lib/bpf/Build |  2 +-
>  tools/lib/bpf/bpf.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  tools/lib/bpf/bpf.h | 16 +++++++++++++++
>  3 files changed, 73 insertions(+), 1 deletion(-)
>  create mode 100644 tools/lib/bpf/bpf.c
>  create mode 100644 tools/lib/bpf/bpf.h
> 
> diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build
> index a316484..d874975 100644
> --- a/tools/lib/bpf/Build
> +++ b/tools/lib/bpf/Build
> @@ -1 +1 @@
> -libbpf-y := libbpf.o
> +libbpf-y := libbpf.o bpf.o
> diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
> new file mode 100644
> index 0000000..7481923
> --- /dev/null
> +++ b/tools/lib/bpf/bpf.c
> @@ -0,0 +1,56 @@
> +/*
> + * common eBPF ELF operations.
> + *
> + * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
> + * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
> + * Copyright (C) 2015 Huawei Inc.
> + */
> +
> +#include <stdlib.h>
> +#include <memory.h>
> +#include <unistd.h>
> +#include <asm/unistd.h>
> +#include <linux/bpf.h>
> +#include "bpf.h"
> +
> +/* When building perf, unistd.h is override. __NR_bpf by ourself. */
> +#if defined(__i386__)
> +#ifndef __NR_bpf
> +# define __NR_bpf 357
> +#endif
> +#endif
> +
> +#if defined(__x86_64__)
> +#ifndef __NR_bpf
> +# define __NR_bpf 321
> +#endif
> +#endif
> +
> +#if defined(__aarch64__)
> +#ifndef __NR_bpf
> +# define __NR_bpf 280
> +#endif
> +#endif
> +
> +#ifndef __NR_bpf
> +# error __NR_bpf not defined. libbpf does not support your arch.
> +#endif

Why not doing this way?

#ifndef __NR_bpf
# if defined(__i386__)
#  define __NR_bpf 357
# elif defined(__x86_64)
#  define __NR_bpf 321
# elif defined(__aarch64__)
#  define __NR_bpf 280
# else
#  error __NR_bpf not defined. libbpf does not support your arch.
# endif
#endif

Thanks,
Namhyung


> +
> +static int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, unsigned int size)
> +{
> +	return syscall(__NR_bpf, cmd, attr, size);
> +}
> +
> +int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
> +		   int max_entries)
> +{
> +	union bpf_attr attr;
> +	memset(&attr, '\0', sizeof(attr));
> +	
> +	attr.map_type = map_type;
> +	attr.key_size = key_size;
> +	attr.value_size = value_size;
> +	attr.max_entries = max_entries;
> +
> +	return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
> +}
> diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
> new file mode 100644
> index 0000000..28f7942
> --- /dev/null
> +++ b/tools/lib/bpf/bpf.h
> @@ -0,0 +1,16 @@
> +/*
> + * common eBPF ELF operations.
> + *
> + * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
> + * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
> + * Copyright (C) 2015 Huawei Inc.
> + */
> +#ifndef __BPF_BPF_H
> +#define __BPF_BPF_H
> +
> +#include <linux/bpf.h>
> +
> +int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
> +		   int max_entries);
> +
> +#endif
> -- 
> 1.8.3.4
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-05-29  3:35               ` Alexei Starovoitov
  2015-05-29  3:59                 ` Wangnan (F)
@ 2015-06-01  2:12                 ` Namhyung Kim
  2015-06-01  5:19                   ` Wangnan (F)
  1 sibling, 1 reply; 62+ messages in thread
From: Namhyung Kim @ 2015-06-01  2:12 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Wangnan (F),
	paulus, a.p.zijlstra, mingo, acme, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama, xiakaixu 00238161

Hi Alexei and Wang,

On Thu, May 28, 2015 at 08:35:19PM -0700, Alexei Starovoitov wrote:
> On Thu, May 28, 2015 at 03:14:44PM +0800, Wangnan (F) wrote:
> > On 2015/5/28 14:09, Alexei Starovoitov wrote:
> > >On Thu, May 28, 2015 at 11:09:50AM +0800, Wangnan (F) wrote:
> > For me, enable eBPF program to read PMU counter is the first thing need to
> > be done.
> > The other thing is enabling eBPF programs to bring some information to perf
> > sample.
> > 
> > Here is an example to show my idea.
> > 
> > I have a program which:
> > 
> > int main()
> > {
> >   while(1) {
> >     read(...);
> >     /* do A */
> >     write(...);
> >     /* do B */
> >   }
> > }
> > 
> > Then by using following script:
> > 
> >  SEC("enter=sys_write $outdata:u64")
> >  int enter_sys_write(...) {
> >    u64 cycles_cnt = bpf_read_pmu(&cycles_pmu);
> >    bpf_store_value(cycles_cnt);
> >    return 1;
> >  }
> > 
> >  SEC("enter=sys_read $outdata:u64")
> >  int enter_sys_read(...) {
> >    u64 cycles_cnt = bpf_read_pmu(&cycles_pmu);
> >    bpf_store_value(cycles_cnt);
> >    return 1;
> >  }
> > 
> > by 'perf script', we can check the counter of cycles at each points, then we
> > are allowed
> > to compute the number of cycles between any two sampling points. This way we
> > can compute
> > how many cycles taken by A and B. If instruction counter is also recorded,
> > we will know
> > the IPC of A and B.
> 
> Agree. That's useful. That's exactly what I meant by
> "compute a number of cache misses between two kprobe events".
> The overhead is less when bpf program computes the cycle and instruction
> delta, computes IPC and passes only final IPC numbers to the user space.
> It can even average IPC over time.
> For some very frequent events it can read cycle_cnt on sys_entry_read,
> then read it on sys_exit_read, compute delta and average it into the map.
> User space can read the map every second or every 10 seconds and print
> nice graph.

Looks very interesting and useful indeed!

> As far as 'bpf_store_value' goes... I was thinking to expose perf ring_buffer
> to bpf programs, so that program can stream any data to perf that receives
> it via mmap. Then you don't need this '$outdata' hack.

Then we need to define and pass the format of such data so that perf
tools can read and process the data.  IIRC Masami suggested to have an
additional user event type for inserting/injecting non-perf events -
like PERF_RECORD_USER_DEFINED_TYPE?  And its contents is something
similar to tracepoint event format file so that we can reuse existing
code to parse the event definition.

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-06-01  2:12                 ` Namhyung Kim
@ 2015-06-01  5:19                   ` Wangnan (F)
  2015-06-01  6:03                     ` Namhyung Kim
  0 siblings, 1 reply; 62+ messages in thread
From: Wangnan (F) @ 2015-06-01  5:19 UTC (permalink / raw)
  To: Namhyung Kim, Alexei Starovoitov
  Cc: paulus, a.p.zijlstra, mingo, acme, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama, xiakaixu 00238161



On 2015/6/1 10:12, Namhyung Kim wrote:
> Hi Alexei and Wang,
>
> On Thu, May 28, 2015 at 08:35:19PM -0700, Alexei Starovoitov wrote:
>> On Thu, May 28, 2015 at 03:14:44PM +0800, Wangnan (F) wrote:
>>> On 2015/5/28 14:09, Alexei Starovoitov wrote:
>>>> On Thu, May 28, 2015 at 11:09:50AM +0800, Wangnan (F) wrote:
>>> For me, enable eBPF program to read PMU counter is the first thing need to
>>> be done.
>>> The other thing is enabling eBPF programs to bring some information to perf
>>> sample.
>>>
>>> Here is an example to show my idea.
>>>
>>> I have a program which:
>>>
>>> int main()
>>> {
>>>    while(1) {
>>>      read(...);
>>>      /* do A */
>>>      write(...);
>>>      /* do B */
>>>    }
>>> }
>>>
>>> Then by using following script:
>>>
>>>   SEC("enter=sys_write $outdata:u64")
>>>   int enter_sys_write(...) {
>>>     u64 cycles_cnt = bpf_read_pmu(&cycles_pmu);
>>>     bpf_store_value(cycles_cnt);
>>>     return 1;
>>>   }
>>>
>>>   SEC("enter=sys_read $outdata:u64")
>>>   int enter_sys_read(...) {
>>>     u64 cycles_cnt = bpf_read_pmu(&cycles_pmu);
>>>     bpf_store_value(cycles_cnt);
>>>     return 1;
>>>   }
>>>
>>> by 'perf script', we can check the counter of cycles at each points, then we
>>> are allowed
>>> to compute the number of cycles between any two sampling points. This way we
>>> can compute
>>> how many cycles taken by A and B. If instruction counter is also recorded,
>>> we will know
>>> the IPC of A and B.
>> Agree. That's useful. That's exactly what I meant by
>> "compute a number of cache misses between two kprobe events".
>> The overhead is less when bpf program computes the cycle and instruction
>> delta, computes IPC and passes only final IPC numbers to the user space.
>> It can even average IPC over time.
>> For some very frequent events it can read cycle_cnt on sys_entry_read,
>> then read it on sys_exit_read, compute delta and average it into the map.
>> User space can read the map every second or every 10 seconds and print
>> nice graph.
> Looks very interesting and useful indeed!
>
>> As far as 'bpf_store_value' goes... I was thinking to expose perf ring_buffer
>> to bpf programs, so that program can stream any data to perf that receives
>> it via mmap. Then you don't need this '$outdata' hack.
> Then we need to define and pass the format of such data so that perf
> tools can read and process the data.  IIRC Masami suggested to have an
> additional user event type for inserting/injecting non-perf events -
> like PERF_RECORD_USER_DEFINED_TYPE?  And its contents is something
> similar to tracepoint event format file so that we can reuse existing
> code to parse the event definition.

Is it possible to expose such format through 
/sys/kernel/debug/tracing/events/*/*/format
so we can avoid extra work on perf side and make it accessable by both 
perf and ftrace?

Currently we do this by opening an internal PMU and adding a common
field in trace_define_common_fields(). By reading that PMU in
tracing_generic_entry_update() we are able to collect its value by both 
perf and ftrace, both
kprobe events and tracepoints (the implementation is ugly. We have to 
hardwire the
PMU because alerting common field dynamically is hard. If we want to 
trace multiple PMUs then
recompiling is required). In serval usecase, we found that using ftrace 
should be better
because the cost of perf is higher.

Although currently BPF programs can only get executed if it traced by 
perf, I think we can
extend it to ftrace (but not sure how to do it now...).

Currently I'm still working on perf bpf stuffs. I think it has almost 
done. The next step
should be solving arguments passing problem. After that we should enable 
eBPF programs to
read hardware PMU. Outputting should be the final step. I'm glad to see 
many people are
thinking on it. Please keep me in the loop if you have any new idea on 
this area.

Thank you.

> Thanks,
> Namhyung



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 17/29] bpf tools: Relocate eBPF programs
  2015-05-27  5:19 ` [RFC PATCH v4 17/29] bpf tools: Relocate eBPF programs Wang Nan
@ 2015-06-01  5:32   ` Namhyung Kim
  2015-06-01  6:36     ` Wangnan (F)
  0 siblings, 1 reply; 62+ messages in thread
From: Namhyung Kim @ 2015-06-01  5:32 UTC (permalink / raw)
  To: Wang Nan
  Cc: paulus, a.p.zijlstra, mingo, acme, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama

On Wed, May 27, 2015 at 05:19:52AM +0000, Wang Nan wrote:
> If an eBPF program access a map, LLVM generates a relocated load
> instruction. To enable the usage of that map, relocation must be done
> by replacing original instructions by map loading instructions.
> 
> Based on relocation description collected during 'opening' phase, this
> patch replaces the instructions with map loading with correct map fd.

I think this message is a bit confusing.. How about this?

If an eBPF program accesses a map, LLVM generates a load instruction
with pseudo map fd.  Since actual map fd can only be known after it
loads the map at runtime, it records such information in relocation
section(s).  So in order to access the map, relocation must be done by
replacing original (pseudo) map fd with correct map fd.

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-06-01  5:19                   ` Wangnan (F)
@ 2015-06-01  6:03                     ` Namhyung Kim
  2015-06-01 13:01                       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 62+ messages in thread
From: Namhyung Kim @ 2015-06-01  6:03 UTC (permalink / raw)
  To: Wangnan (F)
  Cc: Alexei Starovoitov, paulus, a.p.zijlstra, mingo, acme, jolsa,
	dsahern, daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama, xiakaixu 00238161

On Mon, Jun 01, 2015 at 01:19:16PM +0800, Wangnan (F) wrote:
> 
> 
> On 2015/6/1 10:12, Namhyung Kim wrote:
> >Hi Alexei and Wang,
> >
> >On Thu, May 28, 2015 at 08:35:19PM -0700, Alexei Starovoitov wrote:
> >>On Thu, May 28, 2015 at 03:14:44PM +0800, Wangnan (F) wrote:
> >>>On 2015/5/28 14:09, Alexei Starovoitov wrote:
> >>As far as 'bpf_store_value' goes... I was thinking to expose perf ring_buffer
> >>to bpf programs, so that program can stream any data to perf that receives
> >>it via mmap. Then you don't need this '$outdata' hack.
> >Then we need to define and pass the format of such data so that perf
> >tools can read and process the data.  IIRC Masami suggested to have an
> >additional user event type for inserting/injecting non-perf events -
> >like PERF_RECORD_USER_DEFINED_TYPE?  And its contents is something
> >similar to tracepoint event format file so that we can reuse existing
> >code to parse the event definition.
> 
> Is it possible to expose such format through
> /sys/kernel/debug/tracing/events/*/*/format
> so we can avoid extra work on perf side and make it accessable by both perf
> and ftrace?

No, I mean export such format through an event in perf.data file.  It
still needs extra work on perf-tools side.  But by using user-defined
event types, there should be no kernel-side work.

Above is just a suggestion how to deal with external data/events in
perf.  But I'm seeing many people want such feature so we need a way
to handle it anyway. ;-)

> 
> Currently we do this by opening an internal PMU and adding a common
> field in trace_define_common_fields(). By reading that PMU in
> tracing_generic_entry_update() we are able to collect its value by both perf
> and ftrace, both
> kprobe events and tracepoints (the implementation is ugly. We have to
> hardwire the
> PMU because alerting common field dynamically is hard. If we want to trace
> multiple PMUs then
> recompiling is required). In serval usecase, we found that using ftrace
> should be better
> because the cost of perf is higher.
> 
> Although currently BPF programs can only get executed if it traced by perf,
> I think we can
> extend it to ftrace (but not sure how to do it now...).
> 
> Currently I'm still working on perf bpf stuffs. I think it has almost done.
> The next step
> should be solving arguments passing problem. After that we should enable
> eBPF programs to
> read hardware PMU. Outputting should be the final step. I'm glad to see many
> people are
> thinking on it. Please keep me in the loop if you have any new idea on this
> area.

Sure thing.  I really thank you to do this work!
Namhyung

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 17/29] bpf tools: Relocate eBPF programs
  2015-06-01  5:32   ` Namhyung Kim
@ 2015-06-01  6:36     ` Wangnan (F)
  0 siblings, 0 replies; 62+ messages in thread
From: Wangnan (F) @ 2015-06-01  6:36 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: paulus, a.p.zijlstra, mingo, acme, jolsa, dsahern, daniel,
	brendan.d.gregg, masami.hiramatsu.pt, lizefan, linux-kernel,
	pi3orama



On 2015/6/1 13:32, Namhyung Kim wrote:
> On Wed, May 27, 2015 at 05:19:52AM +0000, Wang Nan wrote:
>> If an eBPF program access a map, LLVM generates a relocated load
>> instruction. To enable the usage of that map, relocation must be done
>> by replacing original instructions by map loading instructions.
>>
>> Based on relocation description collected during 'opening' phase, this
>> patch replaces the instructions with map loading with correct map fd.
> I think this message is a bit confusing.. How about this?
>
> If an eBPF program accesses a map, LLVM generates a load instruction
> with pseudo map fd.  Since actual map fd can only be known after it

LLVM doesn't generate mapfd. It creates an instruction read a global
structure. something link this:

   ld_64   r1, <MCOperand Expr:(mymap)>
   ...
   call    2

where ld_64 is a (BPF_LD | BPF_IMM | BPF_DW) instruction, src_reg is not
used at all.

What this relocation done is to utilize src_reg, set it to BPF_PSEUDO_MAP_FD
then set the imm field to the fd of the map.

I will update the commit message as follow:

If an eBPF program accesses a map, LLVM generates a load instruction
which loads an absolute address into a register, like this:

   ld_64   r1, <MCOperand Expr:(mymap)>
   ...
   call    2

That ld_64 instruction will be recorded in relocation section.
To enable the usage of that map, relocation must be done by replacing
the immediate value by real map file descriptor so it can be found by
eBPF map functions.

This patch to the relocation work based on information collected by
patch 'bpf tools: Collect relocation sections from SHT_REL sections'.
For each instruction which needs relocation, it inject corresponding
file descriptor to imm field. As a part of protocol, src_reg is set to
BPF_PSEUDO_MAP_FD to notify kernel this is a map loading instruction.




^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section
  2015-06-01  6:03                     ` Namhyung Kim
@ 2015-06-01 13:01                       ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 62+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-06-01 13:01 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Wangnan (F),
	Alexei Starovoitov, paulus, a.p.zijlstra, mingo, jolsa, dsahern,
	daniel, brendan.d.gregg, masami.hiramatsu.pt, lizefan,
	linux-kernel, pi3orama, xiakaixu 00238161, William Cohen

Em Mon, Jun 01, 2015 at 03:03:11PM +0900, Namhyung Kim escreveu:
> On Mon, Jun 01, 2015 at 01:19:16PM +0800, Wangnan (F) wrote:
> > On 2015/6/1 10:12, Namhyung Kim wrote:
> > >On Thu, May 28, 2015 at 08:35:19PM -0700, Alexei Starovoitov wrote:
> > >>On Thu, May 28, 2015 at 03:14:44PM +0800, Wangnan (F) wrote:
> > >>>On 2015/5/28 14:09, Alexei Starovoitov wrote:
> > >>As far as 'bpf_store_value' goes... I was thinking to expose perf ring_buffer
> > >>to bpf programs, so that program can stream any data to perf that receives
> > >>it via mmap. Then you don't need this '$outdata' hack.
> > >Then we need to define and pass the format of such data so that perf
> > >tools can read and process the data.  IIRC Masami suggested to have an
> > >additional user event type for inserting/injecting non-perf events -
> > >like PERF_RECORD_USER_DEFINED_TYPE?  And its contents is something

That would behave mostly like PERF_TYPE_TRACEPOINT but would look for
event /format definitions in another place? Perhaps one that is in a per
buildid location, i.e. each library has its own place to store such
field definitions, and by tying it to a particular version, it could
change it as it see fit?

> > >similar to tracepoint event format file so that we can reuse existing
> > >code to parse the event definition.

> > Is it possible to expose such format through
> > /sys/kernel/debug/tracing/events/*/*/format
> > so we can avoid extra work on perf side and make it accessable by both perf
> > and ftrace?

> No, I mean export such format through an event in perf.data file.  It
> still needs extra work on perf-tools side.  But by using user-defined
> event types, there should be no kernel-side work.
> 
> Above is just a suggestion how to deal with external data/events in
> perf.  But I'm seeing many people want such feature so we need a way
> to handle it anyway. ;-)

Right, having a way to map from a { attr.type = PERF_TYPE_USER_DEFINED,
attr.config = N }, to a description of the fields, like what we have now
for tracepoints, kprobes and uprobes, seems the way to reuse most of the
existing infrastructure.

We then collect just the /format files referenced in the perf.data file
and all seems to be in place, no?

- Arnaldo

^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2015-06-01 13:01 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-27  5:19 [RFC PATCH v4 00/29] perf tools: filtering events using eBPF programs Wang Nan
2015-05-27  5:19 ` [RFC PATCH v4 01/29] tools: Add __aligned_u64 to types.h Wang Nan
2015-05-27 13:00   ` Arnaldo Carvalho de Melo
2015-05-28  0:28     ` Wangnan (F)
2015-05-28  0:31       ` Arnaldo Carvalho de Melo
2015-05-27  5:19 ` [RFC PATCH v4 02/29] perf tools: Move linux/kernel.h to tools/include Wang Nan
2015-05-27 13:03   ` Arnaldo Carvalho de Melo
2015-05-27  5:19 ` [RFC PATCH v4 03/29] perf tools: Move linux/{list.h,poison.h} " Wang Nan
2015-05-27 13:15   ` Arnaldo Carvalho de Melo
2015-05-27 13:21     ` Arnaldo Carvalho de Melo
2015-05-27 15:30       ` Arnaldo Carvalho de Melo
2015-05-27  5:19 ` [RFC PATCH v4 04/29] bpf tools: Introduce 'bpf' library to tools Wang Nan
2015-05-27  5:19 ` [RFC PATCH v4 05/29] bpf tools: Allow caller to set printing function Wang Nan
2015-05-29 13:35   ` Namhyung Kim
2015-05-27  5:19 ` [RFC PATCH v4 06/29] bpf tools: Open eBPF object file and do basic validation Wang Nan
2015-05-28  1:44   ` Alexei Starovoitov
2015-05-27  5:19 ` [RFC PATCH v4 07/29] bpf tools: Check endianess and make libbpf fail early Wang Nan
2015-05-28  1:45   ` Alexei Starovoitov
2015-05-27  5:19 ` [RFC PATCH v4 08/29] bpf tools: Iterate over ELF sections to collect information Wang Nan
2015-05-28  1:46   ` Alexei Starovoitov
2015-05-27  5:19 ` [RFC PATCH v4 09/29] bpf tools: Collect version and license from ELF sections Wang Nan
2015-05-28  1:48   ` Alexei Starovoitov
2015-05-28  3:34     ` Wangnan (F)
2015-05-28  5:51       ` Alexei Starovoitov
2015-05-27  5:19 ` [RFC PATCH v4 10/29] bpf tools: Collect map definitions from 'maps' section Wang Nan
2015-05-28  1:53   ` Alexei Starovoitov
2015-05-28  2:03     ` Wangnan (F)
2015-05-28  2:28       ` Alexei Starovoitov
2015-05-28  3:09         ` Wangnan (F)
2015-05-28  6:09           ` Alexei Starovoitov
2015-05-28  7:14             ` Wangnan (F)
2015-05-29  3:35               ` Alexei Starovoitov
2015-05-29  3:59                 ` Wangnan (F)
2015-06-01  2:12                 ` Namhyung Kim
2015-06-01  5:19                   ` Wangnan (F)
2015-06-01  6:03                     ` Namhyung Kim
2015-06-01 13:01                       ` Arnaldo Carvalho de Melo
2015-05-27  5:19 ` [RFC PATCH v4 11/29] bpf tools: Collect symbol table from SHT_SYMTAB section Wang Nan
2015-05-27  5:19 ` [RFC PATCH v4 12/29] bpf tools: Collect eBPF programs from their own sections Wang Nan
2015-05-27  5:19 ` [RFC PATCH v4 13/29] bpf tools: Collect relocation sections from SHT_REL sections Wang Nan
2015-05-27  5:19 ` [RFC PATCH v4 14/29] bpf tools: Record map accessing instructions for each program Wang Nan
2015-05-27  5:19 ` [RFC PATCH v4 15/29] bpf tools: Add bpf.c/h for common bpf operations Wang Nan
2015-05-28  1:55   ` Alexei Starovoitov
2015-05-29 14:44   ` Namhyung Kim
2015-05-27  5:19 ` [RFC PATCH v4 16/29] bpf tools: Create eBPF maps defined in an object file Wang Nan
2015-05-28  1:57   ` Alexei Starovoitov
2015-05-27  5:19 ` [RFC PATCH v4 17/29] bpf tools: Relocate eBPF programs Wang Nan
2015-06-01  5:32   ` Namhyung Kim
2015-06-01  6:36     ` Wangnan (F)
2015-05-27  5:19 ` [RFC PATCH v4 18/29] bpf tools: Introduce bpf_load_program() to bpf.c Wang Nan
2015-05-28  2:14   ` Alexei Starovoitov
2015-05-27  5:19 ` [RFC PATCH v4 19/29] bpf tools: Load eBPF programs in object files into kernel Wang Nan
2015-05-27  5:19 ` [RFC PATCH v4 20/29] bpf tools: Introduce accessors for struct bpf_program Wang Nan
2015-05-27  5:19 ` [RFC PATCH v4 21/29] bpf tools: Introduce accessors for struct bpf_object Wang Nan
2015-05-27  5:19 ` [RFC PATCH v4 22/29] bpf tools: Link all bpf objects onto a list Wang Nan
2015-05-27  5:19 ` [RFC PATCH v4 23/29] perf tools: Make perf depend on libbpf Wang Nan
2015-05-27  5:19 ` [RFC PATCH v4 24/29] perf record: Enable passing bpf object file to --event Wang Nan
2015-05-27  5:20 ` [RFC PATCH v4 25/29] perf tools: Parse probe points of eBPF programs during preparation Wang Nan
2015-05-27  5:20 ` [RFC PATCH v4 26/29] perf record: Probe at kprobe points Wang Nan
2015-05-27  5:20 ` [RFC PATCH v4 27/29] perf record: Load all eBPF object into kernel Wang Nan
2015-05-27  5:20 ` [RFC PATCH v4 28/29] perf tools: Add bpf_fd field to evsel and config it Wang Nan
2015-05-27  5:20 ` [RFC PATCH v4 29/29] perf tools: Attach eBPF program to perf event Wang Nan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).