diff mbox

[09/10] bpf samples: Uses libbpf in tools/lib to deal with BPF operations

Message ID 1450329794-161948-10-git-send-email-wangnan0@huawei.com
State New
Headers show

Commit Message

Wang Nan Dec. 17, 2015, 5:23 a.m. UTC
Since we already have libbpf in tools/lib, there's no need to maintain
a duplicate BPF loading and operations library in samples.

This patch utilises previous introduced utils.[ch], which calls libbpf
to do these work.

The main changing in this relative large patch is very simple:

 1. Makefile modification, makes all hostprogs depend on libbpf.a.
    Add include and library searching patch and rules for linker.
    Remove old bpf_load.o and libbpf.o, replaces them with utils.o

 2. Make sure there are correct 'version' section so the BPF source
    files can be loaded by libbpf.

 3. Uses API provided by utils.h and libbpf.

Signed-off-by: Wang Nan <wangnan0@huawei.com>

Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Alex Gartrell <agartrell@fb.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Brenden Blanco <bblanco@plumgrid.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Daniel Wagner <daniel.wagner@bmw-carit.de>
Cc: David S. Miller <davem@davemloft.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Cc: Yang Shi <yang.shi@linaro.org>
---
 samples/bpf/Makefile            | 65 ++++++++++++++++++---------------
 samples/bpf/fds_example.c       | 26 +++++++-------
 samples/bpf/lathist_user.c      | 13 ++++---
 samples/bpf/sock_example.c      | 13 +++----
 samples/bpf/sockex1_kern.c      |  2 ++
 samples/bpf/sockex1_user.c      | 27 ++++++++------
 samples/bpf/sockex2_kern.c      |  2 ++
 samples/bpf/sockex2_user.c      | 26 ++++++++------
 samples/bpf/sockex3_kern.c      |  2 ++
 samples/bpf/sockex3_user.c      | 23 +++++++-----
 samples/bpf/test_maps.c         | 80 ++++++++++++++++++++---------------------
 samples/bpf/test_verifier.c     | 13 ++++---
 samples/bpf/trace_output_user.c | 17 +++++----
 samples/bpf/tracex1_user.c      |  9 +++--
 samples/bpf/tracex2_user.c      | 31 +++++++++-------
 samples/bpf/tracex3_user.c      | 15 ++++----
 samples/bpf/tracex4_user.c      | 15 ++++----
 samples/bpf/tracex5_user.c      |  9 +++--
 samples/bpf/tracex6_user.c      | 16 ++++-----
 19 files changed, 221 insertions(+), 183 deletions(-)

-- 
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/
diff mbox

Patch

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index edd638b..edb7c04 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -1,6 +1,20 @@ 
 # kbuild trick to avoid linker error. Can be omitted if a module is built.
 obj- := dummy.o
 
+INC_DIR = $(src)/include
+TOOLS_DIR = $(realpath $(srctree))/tools
+TOOLS_LIB_DIR = $(TOOLS_DIR)/lib
+LIBBPF_DIR = $(TOOLS_LIB_DIR)/bpf
+
+$(obj)/libbpf/libbpf.a:
+	$(Q)mkdir -p $(obj)/libbpf
+	$(MAKE) -C $(LIBBPF_DIR) O=$(realpath $(obj))/libbpf CFLAGS= LDFLAGS= V=1 $(realpath $(obj))/libbpf/libbpf.a
+
+HOSTCFLAGS += -I$(TOOLS_LIB_DIR) -I$(INC_DIR)
+HOSTLDFLAGS += -L$(obj)/libbpf
+HOSTCFLAGS += -I$(INC_DIR) -I$(TOOLS_LIB_DIR)
+HOST_LOADLIBES += -lelf -lbpf
+
 # List of programs to build
 hostprogs-y := test_verifier test_maps
 hostprogs-y += sock_example
@@ -17,21 +31,27 @@  hostprogs-y += tracex6
 hostprogs-y += trace_output
 hostprogs-y += lathist
 
-test_verifier-objs := test_verifier.o libbpf.o
-test_maps-objs := test_maps.o libbpf.o
-sock_example-objs := sock_example.o libbpf.o
-fds_example-objs := bpf_load.o libbpf.o fds_example.o
-sockex1-objs := bpf_load.o libbpf.o sockex1_user.o
-sockex2-objs := bpf_load.o libbpf.o sockex2_user.o
-sockex3-objs := bpf_load.o libbpf.o sockex3_user.o
-tracex1-objs := bpf_load.o libbpf.o tracex1_user.o
-tracex2-objs := bpf_load.o libbpf.o tracex2_user.o
-tracex3-objs := bpf_load.o libbpf.o tracex3_user.o
-tracex4-objs := bpf_load.o libbpf.o tracex4_user.o
-tracex5-objs := bpf_load.o libbpf.o tracex5_user.o
-tracex6-objs := bpf_load.o libbpf.o tracex6_user.o
-trace_output-objs := bpf_load.o libbpf.o trace_output_user.o
-lathist-objs := bpf_load.o libbpf.o lathist_user.o
+test_verifier-objs := test_verifier.o
+test_maps-objs := test_maps.o
+sock_example-objs := sock_example.o utils.o
+fds_example-objs := utils.o fds_example.o
+sockex1-objs := utils.o sockex1_user.o
+sockex2-objs := utils.o sockex2_user.o
+sockex3-objs := utils.o sockex3_user.o
+tracex1-objs := utils.o tracex1_user.o
+tracex2-objs := utils.o tracex2_user.o
+tracex3-objs := utils.o tracex3_user.o
+tracex4-objs := utils.o tracex4_user.o
+tracex5-objs := utils.o tracex5_user.o
+tracex6-objs := utils.o tracex6_user.o
+trace_output-objs := utils.o trace_output_user.o
+lathist-objs := utils.o lathist_user.o
+
+define add_depend
+$(foreach m, $(notdir $1), \
+	$(eval $(obj)/$m: $(obj)/libbpf/libbpf.a))
+endef
+$(call add_depend, $(hostprogs-y))
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
@@ -50,19 +70,8 @@  always += lathist_kern.o
 
 HOSTCFLAGS += -I$(objtree)/usr/include
 
-HOSTCFLAGS_bpf_load.o += -I$(objtree)/usr/include -Wno-unused-variable
-HOSTLOADLIBES_fds_example += -lelf
-HOSTLOADLIBES_sockex1 += -lelf
-HOSTLOADLIBES_sockex2 += -lelf
-HOSTLOADLIBES_sockex3 += -lelf
-HOSTLOADLIBES_tracex1 += -lelf
-HOSTLOADLIBES_tracex2 += -lelf
-HOSTLOADLIBES_tracex3 += -lelf
-HOSTLOADLIBES_tracex4 += -lelf -lrt
-HOSTLOADLIBES_tracex5 += -lelf
-HOSTLOADLIBES_tracex6 += -lelf
-HOSTLOADLIBES_trace_output += -lelf -lrt
-HOSTLOADLIBES_lathist += -lelf
+HOSTLOADLIBES_tracex4 += -lrt
+HOSTLOADLIBES_trace_output += -lrt
 
 # point this to your LLVM backend with bpf support
 LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc
diff --git a/samples/bpf/fds_example.c b/samples/bpf/fds_example.c
index e2fd16c..bdcfce0 100644
--- a/samples/bpf/fds_example.c
+++ b/samples/bpf/fds_example.c
@@ -12,8 +12,7 @@ 
 #include <sys/types.h>
 #include <sys/socket.h>
 
-#include "bpf_load.h"
-#include "libbpf.h"
+#include "utils.h"
 
 #define BPF_F_PIN	(1 << 0)
 #define BPF_F_GET	(1 << 1)
@@ -55,11 +54,14 @@  static int bpf_prog_create(const char *object)
 	};
 
 	if (object) {
-		assert(!load_bpf_file((char *)object));
-		return prog_fd[0];
+		struct bpf_object *obj = load_bpf_file((char *)object);
+
+		assert(obj);
+		return get_prog_fd(obj, 0);
 	} else {
-		return bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER,
-				     insns, sizeof(insns), "GPL", 0);
+		return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER,
+					insns, sizeof(insns) / sizeof(insns[0]),
+					"GPL", 0, NULL, 0);
 	}
 }
 
@@ -73,22 +75,22 @@  static int bpf_do_map(const char *file, uint32_t flags, uint32_t key,
 		printf("bpf: map fd:%d (%s)\n", fd, strerror(errno));
 		assert(fd > 0);
 
-		ret = bpf_obj_pin(fd, file);
+		ret = bpf_pin_object(fd, file);
 		printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno));
 		assert(ret == 0);
 	} else {
-		fd = bpf_obj_get(file);
+		fd = bpf_get_pinned_object(file);
 		printf("bpf: get fd:%d (%s)\n", fd, strerror(errno));
 		assert(fd > 0);
 	}
 
 	if ((flags & BPF_F_KEY_VAL) == BPF_F_KEY_VAL) {
-		ret = bpf_update_elem(fd, &key, &value, 0);
+		ret = bpf_map_update_elem(fd, &key, &value, 0);
 		printf("bpf: fd:%d u->(%u:%u) ret:(%d,%s)\n", fd, key, value,
 		       ret, strerror(errno));
 		assert(ret == 0);
 	} else if (flags & BPF_F_KEY) {
-		ret = bpf_lookup_elem(fd, &key, &value);
+		ret = bpf_map_lookup_elem(fd, &key, &value);
 		printf("bpf: fd:%d l->(%u):%u ret:(%d,%s)\n", fd, key, value,
 		       ret, strerror(errno));
 		assert(ret == 0);
@@ -106,11 +108,11 @@  static int bpf_do_prog(const char *file, uint32_t flags, const char *object)
 		printf("bpf: prog fd:%d (%s)\n", fd, strerror(errno));
 		assert(fd > 0);
 
-		ret = bpf_obj_pin(fd, file);
+		ret = bpf_pin_object(fd, file);
 		printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno));
 		assert(ret == 0);
 	} else {
-		fd = bpf_obj_get(file);
+		fd = bpf_get_pinned_object(file);
 		printf("bpf: get fd:%d (%s)\n", fd, strerror(errno));
 		assert(fd > 0);
 	}
diff --git a/samples/bpf/lathist_user.c b/samples/bpf/lathist_user.c
index 65da8c1..9160af8 100644
--- a/samples/bpf/lathist_user.c
+++ b/samples/bpf/lathist_user.c
@@ -10,8 +10,7 @@ 
 #include <stdlib.h>
 #include <signal.h>
 #include <linux/bpf.h>
-#include "libbpf.h"
-#include "bpf_load.h"
+#include "utils.h"
 
 #define MAX_ENTRIES	20
 #define MAX_CPU		4
@@ -73,7 +72,7 @@  static void get_data(int fd)
 	for (c = 0; c < MAX_CPU; c++) {
 		for (i = 0; i < MAX_ENTRIES; i++) {
 			key = c * MAX_ENTRIES + i;
-			bpf_lookup_elem(fd, &key, &value);
+			bpf_map_lookup_elem(fd, &key, &value);
 
 			cpu_hist[c].data[i] = value;
 			if (value > cpu_hist[c].max)
@@ -85,16 +84,16 @@  static void get_data(int fd)
 int main(int argc, char **argv)
 {
 	char filename[256];
+	struct bpf_object *obj;
 
 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 
-	if (load_bpf_file(filename)) {
-		printf("%s", bpf_log_buf);
+	obj = load_bpf_file(filename);
+	if (!obj)
 		return 1;
-	}
 
 	while (1) {
-		get_data(map_fd[1]);
+		get_data(get_map_fd(obj, 1));
 		print_hist();
 		sleep(5);
 	}
diff --git a/samples/bpf/sock_example.c b/samples/bpf/sock_example.c
index a0ce251..a6a875f 100644
--- a/samples/bpf/sock_example.c
+++ b/samples/bpf/sock_example.c
@@ -26,7 +26,7 @@ 
 #include <linux/if_ether.h>
 #include <linux/ip.h>
 #include <stddef.h>
-#include "libbpf.h"
+#include "utils.h"
 
 static int test_sock(void)
 {
@@ -55,8 +55,9 @@  static int test_sock(void)
 		BPF_EXIT_INSN(),
 	};
 
-	prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog),
-				"GPL", 0);
+	prog_fd = bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog,
+				   sizeof(prog) / sizeof(prog[0]),
+				   "GPL", 0, NULL, 0);
 	if (prog_fd < 0) {
 		printf("failed to load prog '%s'\n", strerror(errno));
 		goto cleanup;
@@ -72,13 +73,13 @@  static int test_sock(void)
 
 	for (i = 0; i < 10; i++) {
 		key = IPPROTO_TCP;
-		assert(bpf_lookup_elem(map_fd, &key, &tcp_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd, &key, &tcp_cnt) == 0);
 
 		key = IPPROTO_UDP;
-		assert(bpf_lookup_elem(map_fd, &key, &udp_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd, &key, &udp_cnt) == 0);
 
 		key = IPPROTO_ICMP;
-		assert(bpf_lookup_elem(map_fd, &key, &icmp_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd, &key, &icmp_cnt) == 0);
 
 		printf("TCP %lld UDP %lld ICMP %lld packets\n",
 		       tcp_cnt, udp_cnt, icmp_cnt);
diff --git a/samples/bpf/sockex1_kern.c b/samples/bpf/sockex1_kern.c
index ed18e9a..0ab3d9a 100644
--- a/samples/bpf/sockex1_kern.c
+++ b/samples/bpf/sockex1_kern.c
@@ -2,6 +2,7 @@ 
 #include <uapi/linux/if_ether.h>
 #include <uapi/linux/if_packet.h>
 #include <uapi/linux/ip.h>
+#include <linux/version.h>
 #include "bpf_helpers.h"
 
 struct bpf_map_def SEC("maps") my_map = {
@@ -27,3 +28,4 @@  int bpf_prog1(struct __sk_buff *skb)
 	return 0;
 }
 char _license[] SEC("license") = "GPL";
+int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/sockex1_user.c b/samples/bpf/sockex1_user.c
index 678ce46..d1ece36 100644
--- a/samples/bpf/sockex1_user.c
+++ b/samples/bpf/sockex1_user.c
@@ -1,28 +1,33 @@ 
 #include <stdio.h>
 #include <assert.h>
-#include <linux/bpf.h>
-#include "libbpf.h"
-#include "bpf_load.h"
 #include <unistd.h>
 #include <arpa/inet.h>
+#include "utils.h"
 
 int main(int ac, char **argv)
 {
 	char filename[256];
 	FILE *f;
-	int i, sock;
+	int i, sock, map_fd, prog_fd;
+	struct bpf_object *obj;
 
 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 
-	if (load_bpf_file(filename)) {
-		printf("%s", bpf_log_buf);
+	obj = load_bpf_file(filename);
+	if (!obj)
+		return 1;
+
+	map_fd = get_map_fd(obj, 0);
+	prog_fd = get_prog_fd(obj, 0);
+	if (map_fd < 0 || prog_fd < 0) {
+		fprintf(stderr, "failed to get file descriptor\n");
 		return 1;
 	}
 
 	sock = open_raw_sock("lo");
 
-	assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, prog_fd,
-			  sizeof(prog_fd[0])) == 0);
+	assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd,
+			  sizeof(prog_fd)) == 0);
 
 	f = popen("ping -c5 localhost", "r");
 	(void) f;
@@ -32,13 +37,13 @@  int main(int ac, char **argv)
 		int key;
 
 		key = IPPROTO_TCP;
-		assert(bpf_lookup_elem(map_fd[0], &key, &tcp_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd, &key, &tcp_cnt) == 0);
 
 		key = IPPROTO_UDP;
-		assert(bpf_lookup_elem(map_fd[0], &key, &udp_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd, &key, &udp_cnt) == 0);
 
 		key = IPPROTO_ICMP;
-		assert(bpf_lookup_elem(map_fd[0], &key, &icmp_cnt) == 0);
+		assert(bpf_map_lookup_elem(map_fd, &key, &icmp_cnt) == 0);
 
 		printf("TCP %lld UDP %lld ICMP %lld bytes\n",
 		       tcp_cnt, udp_cnt, icmp_cnt);
diff --git a/samples/bpf/sockex2_kern.c b/samples/bpf/sockex2_kern.c
index ba0e177..46e2e77 100644
--- a/samples/bpf/sockex2_kern.c
+++ b/samples/bpf/sockex2_kern.c
@@ -6,6 +6,7 @@ 
 #include <uapi/linux/ip.h>
 #include <uapi/linux/ipv6.h>
 #include <uapi/linux/if_tunnel.h>
+#include <linux/version.h>
 #define IP_MF		0x2000
 #define IP_OFFSET	0x1FFF
 
@@ -219,3 +220,4 @@  int bpf_prog2(struct __sk_buff *skb)
 }
 
 char _license[] SEC("license") = "GPL";
+int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/sockex2_user.c b/samples/bpf/sockex2_user.c
index 29a276d..3df6442 100644
--- a/samples/bpf/sockex2_user.c
+++ b/samples/bpf/sockex2_user.c
@@ -1,10 +1,9 @@ 
 #include <stdio.h>
 #include <assert.h>
-#include <linux/bpf.h>
-#include "libbpf.h"
-#include "bpf_load.h"
 #include <unistd.h>
 #include <arpa/inet.h>
+#include <bpf/bpf.h>
+#include "utils.h"
 
 struct pair {
 	__u64 packets;
@@ -15,19 +14,26 @@  int main(int ac, char **argv)
 {
 	char filename[256];
 	FILE *f;
-	int i, sock;
+	int i, sock, map_fd, prog_fd;
+	struct bpf_object *obj;
 
 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 
-	if (load_bpf_file(filename)) {
-		printf("%s", bpf_log_buf);
+	obj = load_bpf_file(filename);
+	if (!obj)
+		return 1;
+
+	map_fd = get_map_fd(obj, 0);
+	prog_fd = get_prog_fd(obj, 0);
+	if (map_fd < 0 || prog_fd < 0) {
+		fprintf(stderr, "failed to get file descriptor\n");
 		return 1;
 	}
 
 	sock = open_raw_sock("lo");
 
-	assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, prog_fd,
-			  sizeof(prog_fd[0])) == 0);
+	assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd,
+			  sizeof(prog_fd)) == 0);
 
 	f = popen("ping -c5 localhost", "r");
 	(void) f;
@@ -36,8 +42,8 @@  int main(int ac, char **argv)
 		int key = 0, next_key;
 		struct pair value;
 
-		while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
-			bpf_lookup_elem(map_fd[0], &next_key, &value);
+		while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0) {
+			bpf_map_lookup_elem(map_fd, &next_key, &value);
 			printf("ip %s bytes %lld packets %lld\n",
 			       inet_ntoa((struct in_addr){htonl(next_key)}),
 			       value.bytes, value.packets);
diff --git a/samples/bpf/sockex3_kern.c b/samples/bpf/sockex3_kern.c
index 41ae2fd..6ac0d17 100644
--- a/samples/bpf/sockex3_kern.c
+++ b/samples/bpf/sockex3_kern.c
@@ -13,6 +13,7 @@ 
 #include <uapi/linux/ipv6.h>
 #include <uapi/linux/if_tunnel.h>
 #include <uapi/linux/mpls.h>
+#include <linux/version.h>
 #define IP_MF		0x2000
 #define IP_OFFSET	0x1FFF
 
@@ -288,3 +289,4 @@  int main_prog(struct __sk_buff *skb)
 }
 
 char _license[] SEC("license") = "GPL";
+int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/sockex3_user.c b/samples/bpf/sockex3_user.c
index 2617772..99a7126 100644
--- a/samples/bpf/sockex3_user.c
+++ b/samples/bpf/sockex3_user.c
@@ -1,10 +1,10 @@ 
 #include <stdio.h>
 #include <assert.h>
 #include <linux/bpf.h>
-#include "libbpf.h"
-#include "bpf_load.h"
 #include <unistd.h>
 #include <arpa/inet.h>
+#include <bpf/bpf.h>
+#include "utils.h"
 
 struct flow_keys {
 	__be32 src;
@@ -25,18 +25,25 @@  int main(int argc, char **argv)
 {
 	char filename[256];
 	FILE *f;
-	int i, sock;
+	int i, sock, map_fd, prog_fd;
+	struct bpf_object *obj;
 
 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 
-	if (load_bpf_file(filename)) {
-		printf("%s", bpf_log_buf);
+	obj = load_bpf_file(filename);
+	if (!obj)
+		return 1;
+
+	map_fd = get_map_fd(obj, 2);
+	prog_fd = get_prog_fd(obj, 4);
+	if (map_fd < 0 || prog_fd < 0) {
+		fprintf(stderr, "failed to get file descriptor\n");
 		return 1;
 	}
 
 	sock = open_raw_sock("lo");
 
-	assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd[4],
+	assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd,
 			  sizeof(__u32)) == 0);
 
 	if (argc > 1)
@@ -51,8 +58,8 @@  int main(int argc, char **argv)
 
 		sleep(1);
 		printf("IP     src.port -> dst.port               bytes      packets\n");
-		while (bpf_get_next_key(map_fd[2], &key, &next_key) == 0) {
-			bpf_lookup_elem(map_fd[2], &next_key, &value);
+		while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0) {
+			bpf_map_lookup_elem(map_fd, &next_key, &value);
 			printf("%s.%05d -> %s.%05d %12lld %12lld\n",
 			       inet_ntoa((struct in_addr){htonl(next_key.src)}),
 			       next_key.port16[0],
diff --git a/samples/bpf/test_maps.c b/samples/bpf/test_maps.c
index 6299ee9..435d55e 100644
--- a/samples/bpf/test_maps.c
+++ b/samples/bpf/test_maps.c
@@ -15,7 +15,7 @@ 
 #include <assert.h>
 #include <sys/wait.h>
 #include <stdlib.h>
-#include "libbpf.h"
+#include "utils.h"
 
 /* sanity tests for map API */
 static void test_hashmap_sanity(int i, void *data)
@@ -32,59 +32,59 @@  static void test_hashmap_sanity(int i, void *data)
 	key = 1;
 	value = 1234;
 	/* insert key=1 element */
-	assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
+	assert(bpf_map_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
 
 	value = 0;
 	/* BPF_NOEXIST means: add new element if it doesn't exist */
-	assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
+	assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
 	       /* key=1 already exists */
 	       errno == EEXIST);
 
-	assert(bpf_update_elem(map_fd, &key, &value, -1) == -1 && errno == EINVAL);
+	assert(bpf_map_update_elem(map_fd, &key, &value, -1) == -1 && errno == EINVAL);
 
 	/* check that key=1 can be found */
-	assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 1234);
+	assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0 && value == 1234);
 
 	key = 2;
 	/* check that key=2 is not found */
-	assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);
+	assert(bpf_map_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);
 
 	/* BPF_EXIST means: update existing element */
-	assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 &&
+	assert(bpf_map_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 &&
 	       /* key=2 is not there */
 	       errno == ENOENT);
 
 	/* insert key=2 element */
-	assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
+	assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
 
 	/* key=1 and key=2 were inserted, check that key=0 cannot be inserted
 	 * due to max_entries limit
 	 */
 	key = 0;
-	assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
+	assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
 	       errno == E2BIG);
 
 	/* check that key = 0 doesn't exist */
-	assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);
+	assert(bpf_map_delete_elem(map_fd, &key) == -1 && errno == ENOENT);
 
 	/* iterate over two elements */
-	assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 &&
+	assert(bpf_map_get_next_key(map_fd, &key, &next_key) == 0 &&
 	       (next_key == 1 || next_key == 2));
-	assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 &&
+	assert(bpf_map_get_next_key(map_fd, &next_key, &next_key) == 0 &&
 	       (next_key == 1 || next_key == 2));
-	assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 &&
+	assert(bpf_map_get_next_key(map_fd, &next_key, &next_key) == -1 &&
 	       errno == ENOENT);
 
 	/* delete both elements */
 	key = 1;
-	assert(bpf_delete_elem(map_fd, &key) == 0);
+	assert(bpf_map_delete_elem(map_fd, &key) == 0);
 	key = 2;
-	assert(bpf_delete_elem(map_fd, &key) == 0);
-	assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);
+	assert(bpf_map_delete_elem(map_fd, &key) == 0);
+	assert(bpf_map_delete_elem(map_fd, &key) == -1 && errno == ENOENT);
 
 	key = 0;
 	/* check that map is empty */
-	assert(bpf_get_next_key(map_fd, &key, &next_key) == -1 &&
+	assert(bpf_map_get_next_key(map_fd, &key, &next_key) == -1 &&
 	       errno == ENOENT);
 	close(map_fd);
 }
@@ -103,41 +103,41 @@  static void test_arraymap_sanity(int i, void *data)
 	key = 1;
 	value = 1234;
 	/* insert key=1 element */
-	assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
+	assert(bpf_map_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
 
 	value = 0;
-	assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
+	assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
 	       errno == EEXIST);
 
 	/* check that key=1 can be found */
-	assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 1234);
+	assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0 && value == 1234);
 
 	key = 0;
 	/* check that key=0 is also found and zero initialized */
-	assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 0);
+	assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0 && value == 0);
 
 
 	/* key=0 and key=1 were inserted, check that key=2 cannot be inserted
 	 * due to max_entries limit
 	 */
 	key = 2;
-	assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 &&
+	assert(bpf_map_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 &&
 	       errno == E2BIG);
 
 	/* check that key = 2 doesn't exist */
-	assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);
+	assert(bpf_map_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);
 
 	/* iterate over two elements */
-	assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 &&
+	assert(bpf_map_get_next_key(map_fd, &key, &next_key) == 0 &&
 	       next_key == 0);
-	assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 &&
+	assert(bpf_map_get_next_key(map_fd, &next_key, &next_key) == 0 &&
 	       next_key == 1);
-	assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 &&
+	assert(bpf_map_get_next_key(map_fd, &next_key, &next_key) == -1 &&
 	       errno == ENOENT);
 
 	/* delete shouldn't succeed */
 	key = 1;
-	assert(bpf_delete_elem(map_fd, &key) == -1 && errno == EINVAL);
+	assert(bpf_map_delete_elem(map_fd, &key) == -1 && errno == EINVAL);
 
 	close(map_fd);
 }
@@ -163,21 +163,21 @@  static void test_map_large(void)
 	for (i = 0; i < MAP_SIZE; i++) {
 		key = (struct bigkey) {.c = i};
 		value = i;
-		assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
+		assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
 	}
 	key.c = -1;
-	assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
+	assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
 	       errno == E2BIG);
 
 	/* iterate through all elements */
 	for (i = 0; i < MAP_SIZE; i++)
-		assert(bpf_get_next_key(map_fd, &key, &key) == 0);
-	assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
+		assert(bpf_map_get_next_key(map_fd, &key, &key) == 0);
+	assert(bpf_map_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
 
 	key.c = 0;
-	assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 0);
+	assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0 && value == 0);
 	key.a = 1;
-	assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);
+	assert(bpf_map_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);
 
 	close(map_fd);
 }
@@ -225,9 +225,9 @@  static void do_work(int fn, void *data)
 	for (i = fn; i < MAP_SIZE; i += TASKS) {
 		key = value = i;
 		if (do_update)
-			assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
+			assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
 		else
-			assert(bpf_delete_elem(map_fd, &key) == 0);
+			assert(bpf_map_delete_elem(map_fd, &key) == 0);
 	}
 }
 
@@ -254,19 +254,19 @@  static void test_map_parallel(void)
 	run_parallel(TASKS, do_work, data);
 
 	/* check that key=0 is already there */
-	assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
+	assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
 	       errno == EEXIST);
 
 	/* check that all elements were inserted */
 	key = -1;
 	for (i = 0; i < MAP_SIZE; i++)
-		assert(bpf_get_next_key(map_fd, &key, &key) == 0);
-	assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
+		assert(bpf_map_get_next_key(map_fd, &key, &key) == 0);
+	assert(bpf_map_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
 
 	/* another check for all elements */
 	for (i = 0; i < MAP_SIZE; i++) {
 		key = MAP_SIZE - i - 1;
-		assert(bpf_lookup_elem(map_fd, &key, &value) == 0 &&
+		assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0 &&
 		       value == key);
 	}
 
@@ -276,7 +276,7 @@  static void test_map_parallel(void)
 
 	/* nothing should be left */
 	key = -1;
-	assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
+	assert(bpf_map_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
 }
 
 int main(void)
diff --git a/samples/bpf/test_verifier.c b/samples/bpf/test_verifier.c
index 563c507..0566fc0 100644
--- a/samples/bpf/test_verifier.c
+++ b/samples/bpf/test_verifier.c
@@ -17,13 +17,17 @@ 
 #include <stddef.h>
 #include <stdbool.h>
 #include <sys/resource.h>
-#include "libbpf.h"
+#include "utils.h"
+#include <bpf/bpf.h>
 
 #define MAX_INSNS 512
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
 
 #define MAX_FIXUPS 8
 
+#define LOG_BUF_SIZE 65536
+static char bpf_log_buf[LOG_BUF_SIZE];
+
 struct bpf_test {
 	const char *descr;
 	struct bpf_insn	insns[MAX_INSNS];
@@ -1250,9 +1254,10 @@  static int test(void)
 		}
 		printf("#%d %s ", i, tests[i].descr);
 
-		prog_fd = bpf_prog_load(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER,
-					prog, prog_len * sizeof(struct bpf_insn),
-					"GPL", 0);
+		bpf_log_buf[0] = '\0';
+		prog_fd = bpf_load_program(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER,
+					   prog, prog_len, "GPL", 0,
+					   bpf_log_buf, sizeof(bpf_log_buf));
 
 		if (unpriv && tests[i].result_unpriv != UNDEF)
 			expected_result = tests[i].result_unpriv;
diff --git a/samples/bpf/trace_output_user.c b/samples/bpf/trace_output_user.c
index 661a7d0..4ef02cb 100644
--- a/samples/bpf/trace_output_user.c
+++ b/samples/bpf/trace_output_user.c
@@ -19,8 +19,7 @@ 
 #include <sys/mman.h>
 #include <time.h>
 #include <signal.h>
-#include "libbpf.h"
-#include "bpf_load.h"
+#include "utils.h"
 
 static int pmu_fd;
 
@@ -61,7 +60,7 @@  struct perf_event_sample {
 	char data[];
 };
 
-void perf_event_read(print_fn fn)
+static void perf_event_read(print_fn fn)
 {
 	__u64 data_tail = header->data_tail;
 	__u64 data_head = header->data_head;
@@ -150,7 +149,7 @@  static void print_bpf_output(void *data, int size)
 	}
 }
 
-static void test_bpf_perf_event(void)
+static void test_bpf_perf_event(int map_fd)
 {
 	struct perf_event_attr attr = {
 		.sample_type = PERF_SAMPLE_RAW,
@@ -162,7 +161,7 @@  static void test_bpf_perf_event(void)
 	pmu_fd = perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
 
 	assert(pmu_fd >= 0);
-	assert(bpf_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0);
+	assert(bpf_map_update_elem(map_fd, &key, &pmu_fd, BPF_ANY) == 0);
 	ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
 }
 
@@ -170,15 +169,15 @@  int main(int argc, char **argv)
 {
 	char filename[256];
 	FILE *f;
+	struct bpf_object *obj;
 
 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 
-	if (load_bpf_file(filename)) {
-		printf("%s", bpf_log_buf);
+	obj = load_bpf_file(filename);
+	if (!obj)
 		return 1;
-	}
 
-	test_bpf_perf_event();
+	test_bpf_perf_event(get_map_fd(obj, 0));
 
 	if (perf_event_mmap(pmu_fd) < 0)
 		return 1;
diff --git a/samples/bpf/tracex1_user.c b/samples/bpf/tracex1_user.c
index 31a4818..0652339 100644
--- a/samples/bpf/tracex1_user.c
+++ b/samples/bpf/tracex1_user.c
@@ -1,20 +1,19 @@ 
 #include <stdio.h>
 #include <linux/bpf.h>
 #include <unistd.h>
-#include "libbpf.h"
-#include "bpf_load.h"
+#include "utils.h"
 
 int main(int ac, char **argv)
 {
 	FILE *f;
 	char filename[256];
+	struct bpf_object *obj;
 
 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 
-	if (load_bpf_file(filename)) {
-		printf("%s", bpf_log_buf);
+	obj = load_bpf_file(filename);
+	if (!obj)
 		return 1;
-	}
 
 	f = popen("taskset 1 ping -c5 localhost", "r");
 	(void) f;
diff --git a/samples/bpf/tracex2_user.c b/samples/bpf/tracex2_user.c
index cd0241c..86700bb 100644
--- a/samples/bpf/tracex2_user.c
+++ b/samples/bpf/tracex2_user.c
@@ -4,8 +4,9 @@ 
 #include <signal.h>
 #include <linux/bpf.h>
 #include <string.h>
-#include "libbpf.h"
-#include "bpf_load.h"
+#include <bpf/libbpf.h>
+#include <bpf/bpf.h>
+#include "utils.h"
 
 #define MAX_INDEX	64
 #define MAX_STARS	38
@@ -44,12 +45,12 @@  static void print_hist_for_pid(int fd, void *task)
 	long max_value = 0;
 	int i, ind;
 
-	while (bpf_get_next_key(fd, &key, &next_key) == 0) {
+	while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
 		if (memcmp(&next_key, task, SIZE)) {
 			key = next_key;
 			continue;
 		}
-		bpf_lookup_elem(fd, &next_key, &value);
+		bpf_map_lookup_elem(fd, &next_key, &value);
 		ind = next_key.index;
 		data[ind] = value;
 		if (value && ind > max_ind)
@@ -76,7 +77,7 @@  static void print_hist(int fd)
 	int task_cnt = 0;
 	int i;
 
-	while (bpf_get_next_key(fd, &key, &next_key) == 0) {
+	while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
 		int found = 0;
 
 		for (i = 0; i < task_cnt; i++)
@@ -97,9 +98,11 @@  static void print_hist(int fd)
 
 }
 
+static int hist_map_fd;
+
 static void int_exit(int sig)
 {
-	print_hist(map_fd[1]);
+	print_hist(hist_map_fd);
 	exit(0);
 }
 
@@ -108,7 +111,8 @@  int main(int ac, char **argv)
 	char filename[256];
 	long key, next_key, value;
 	FILE *f;
-	int i;
+	int i, map_fd;
+	struct bpf_object *obj;
 
 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 
@@ -122,15 +126,16 @@  int main(int ac, char **argv)
 	f = popen("dd if=/dev/zero of=/dev/null count=5000000", "r");
 	(void) f;
 
-	if (load_bpf_file(filename)) {
-		printf("%s", bpf_log_buf);
+	obj = load_bpf_file(filename);
+	if (!obj)
 		return 1;
-	}
+	map_fd = get_map_fd(obj, 0);
+	hist_map_fd = get_map_fd(obj, 1);
 
 	for (i = 0; i < 5; i++) {
 		key = 0;
-		while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
-			bpf_lookup_elem(map_fd[0], &next_key, &value);
+		while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0) {
+			bpf_map_lookup_elem(map_fd, &next_key, &value);
 			printf("location 0x%lx count %ld\n", next_key, value);
 			key = next_key;
 		}
@@ -138,7 +143,7 @@  int main(int ac, char **argv)
 			printf("\n");
 		sleep(1);
 	}
-	print_hist(map_fd[1]);
+	print_hist(hist_map_fd);
 
 	return 0;
 }
diff --git a/samples/bpf/tracex3_user.c b/samples/bpf/tracex3_user.c
index 0aaa933..4c26a6f 100644
--- a/samples/bpf/tracex3_user.c
+++ b/samples/bpf/tracex3_user.c
@@ -11,8 +11,7 @@ 
 #include <stdbool.h>
 #include <string.h>
 #include <linux/bpf.h>
-#include "libbpf.h"
-#include "bpf_load.h"
+#include "utils.h"
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
 
@@ -24,7 +23,7 @@  static void clear_stats(int fd)
 	__u64 value = 0;
 
 	for (key = 0; key < SLOTS; key++)
-		bpf_update_elem(fd, &key, &value, BPF_ANY);
+		bpf_map_update_elem(fd, &key, &value, BPF_ANY);
 }
 
 const char *color[] = {
@@ -83,7 +82,7 @@  static void print_hist(int fd)
 
 	for (key = 0; key < SLOTS; key++) {
 		value = 0;
-		bpf_lookup_elem(fd, &key, &value);
+		bpf_map_lookup_elem(fd, &key, &value);
 		cnt[key] = value;
 		total_events += value;
 		if (value > max_cnt)
@@ -105,13 +104,13 @@  int main(int ac, char **argv)
 {
 	char filename[256];
 	int i;
+	struct bpf_object *obj;
 
 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 
-	if (load_bpf_file(filename)) {
-		printf("%s", bpf_log_buf);
+	obj = load_bpf_file(filename);
+	if (!obj)
 		return 1;
-	}
 
 	for (i = 1; i < ac; i++) {
 		if (strcmp(argv[i], "-a") == 0) {
@@ -142,7 +141,7 @@  int main(int ac, char **argv)
 	for (i = 0; ; i++) {
 		if (i % 20 == 0)
 			print_banner();
-		print_hist(map_fd[1]);
+		print_hist(get_map_fd(obj, 1));
 		sleep(2);
 	}
 
diff --git a/samples/bpf/tracex4_user.c b/samples/bpf/tracex4_user.c
index bc4a3bd..273bd33 100644
--- a/samples/bpf/tracex4_user.c
+++ b/samples/bpf/tracex4_user.c
@@ -12,8 +12,7 @@ 
 #include <string.h>
 #include <time.h>
 #include <linux/bpf.h>
-#include "libbpf.h"
-#include "bpf_load.h"
+#include "utils.h"
 
 struct pair {
 	long long val;
@@ -37,8 +36,8 @@  static void print_old_objects(int fd)
 	key = write(1, "\e[1;1H\e[2J", 12); /* clear screen */
 
 	key = -1;
-	while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
-		bpf_lookup_elem(map_fd[0], &next_key, &v);
+	while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
+		bpf_map_lookup_elem(fd, &next_key, &v);
 		key = next_key;
 		if (val - v.val < 1000000000ll)
 			/* object was allocated more then 1 sec ago */
@@ -51,17 +50,17 @@  static void print_old_objects(int fd)
 int main(int ac, char **argv)
 {
 	char filename[256];
+	struct bpf_object *obj;
 	int i;
 
 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 
-	if (load_bpf_file(filename)) {
-		printf("%s", bpf_log_buf);
+	obj = load_bpf_file(filename);
+	if (!obj)
 		return 1;
-	}
 
 	for (i = 0; ; i++) {
-		print_old_objects(map_fd[1]);
+		print_old_objects(get_map_fd(obj, 0));
 		sleep(1);
 	}
 
diff --git a/samples/bpf/tracex5_user.c b/samples/bpf/tracex5_user.c
index a04dd3c..bcbd7fc 100644
--- a/samples/bpf/tracex5_user.c
+++ b/samples/bpf/tracex5_user.c
@@ -4,8 +4,7 @@ 
 #include <linux/filter.h>
 #include <linux/seccomp.h>
 #include <sys/prctl.h>
-#include "libbpf.h"
-#include "bpf_load.h"
+#include "utils.h"
 
 /* install fake seccomp program to enable seccomp code path inside the kernel,
  * so that our kprobe attached to seccomp_phase1() can be triggered
@@ -27,13 +26,13 @@  int main(int ac, char **argv)
 {
 	FILE *f;
 	char filename[256];
+	struct bpf_object *obj;
 
 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 
-	if (load_bpf_file(filename)) {
-		printf("%s", bpf_log_buf);
+	obj = load_bpf_file(filename);
+	if (!obj)
 		return 1;
-	}
 
 	install_accept_all_seccomp();
 
diff --git a/samples/bpf/tracex6_user.c b/samples/bpf/tracex6_user.c
index 8ea4976..a400e31 100644
--- a/samples/bpf/tracex6_user.c
+++ b/samples/bpf/tracex6_user.c
@@ -8,12 +8,11 @@ 
 #include <sys/ioctl.h>
 #include <linux/perf_event.h>
 #include <linux/bpf.h>
-#include "libbpf.h"
-#include "bpf_load.h"
+#include "utils.h"
 
 #define SAMPLE_PERIOD  0x7fffffffffffffffULL
 
-static void test_bpf_perf_event(void)
+static void test_bpf_perf_event(int map_fd)
 {
 	int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
 	int *pmu_fd = malloc(nr_cpus * sizeof(int));
@@ -36,7 +35,7 @@  static void test_bpf_perf_event(void)
 			goto exit;
 		}
 
-		bpf_update_elem(map_fd[0], &i, &pmu_fd[i], BPF_ANY);
+		bpf_map_update_elem(map_fd, &i, &pmu_fd[i], BPF_ANY);
 		ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0);
 	}
 
@@ -50,22 +49,21 @@  static void test_bpf_perf_event(void)
 exit:
 	for (i = 0; i < nr_cpus; i++)
 		close(pmu_fd[i]);
-	close(map_fd[0]);
 	free(pmu_fd);
 }
 
 int main(int argc, char **argv)
 {
 	char filename[256];
+	struct bpf_object *obj;
 
 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 
-	if (load_bpf_file(filename)) {
-		printf("%s", bpf_log_buf);
+	obj = load_bpf_file(filename);
+	if (!obj)
 		return 1;
-	}
 
-	test_bpf_perf_event();
+	test_bpf_perf_event(get_map_fd(obj, 0));
 	read_trace_pipe();
 
 	return 0;