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;
