aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib/bpf
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2015-06-30 22:13:53 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-08-07 09:16:56 -0400
commit1a5e3fb1e9a4a3e3695cd57c33c169a90d16fd3b (patch)
treebbd48754a0885ae3a861f2374f9d8435fcd34520 /tools/lib/bpf
parentb3f59d66e22b8be4ccae67c8eaffa2cbb9e54eb1 (diff)
bpf tools: Open eBPF object file and do basic validation
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. The zfree() and zclose() functions are introduced to ensure setting NULL pointers and negative file descriptors after resources are released. Signed-off-by: Wang Nan <wangnan0@huawei.com> Acked-by: Alexei Starovoitov <ast@plumgrid.com> Cc: Brendan Gregg <brendan.d.gregg@gmail.com> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: David Ahern <dsahern@gmail.com> Cc: He Kuang <hekuang@huawei.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Kaixu Xia <xiakaixu@huawei.com> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Zefan Li <lizefan@huawei.com> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1435716878-189507-6-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/lib/bpf')
-rw-r--r--tools/lib/bpf/libbpf.c158
-rw-r--r--tools/lib/bpf/libbpf.h8
2 files changed, 166 insertions, 0 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 6f0c13a1fb3c..9e446081fb1c 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -11,8 +11,12 @@
11#include <stdarg.h> 11#include <stdarg.h>
12#include <string.h> 12#include <string.h>
13#include <unistd.h> 13#include <unistd.h>
14#include <fcntl.h>
15#include <errno.h>
14#include <asm/unistd.h> 16#include <asm/unistd.h>
15#include <linux/bpf.h> 17#include <linux/bpf.h>
18#include <libelf.h>
19#include <gelf.h>
16 20
17#include "libbpf.h" 21#include "libbpf.h"
18 22
@@ -52,3 +56,157 @@ void libbpf_set_print(libbpf_print_fn_t warn,
52 __pr_info = info; 56 __pr_info = info;
53 __pr_debug = debug; 57 __pr_debug = debug;
54} 58}
59
60/* Copied from tools/perf/util/util.h */
61#ifndef zfree
62# define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
63#endif
64
65#ifndef zclose
66# define zclose(fd) ({ \
67 int ___err = 0; \
68 if ((fd) >= 0) \
69 ___err = close((fd)); \
70 fd = -1; \
71 ___err; })
72#endif
73
74#ifdef HAVE_LIBELF_MMAP_SUPPORT
75# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ_MMAP
76#else
77# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
78#endif
79
80struct bpf_object {
81 /*
82 * Information when doing elf related work. Only valid if fd
83 * is valid.
84 */
85 struct {
86 int fd;
87 Elf *elf;
88 GElf_Ehdr ehdr;
89 } efile;
90 char path[];
91};
92#define obj_elf_valid(o) ((o)->efile.elf)
93
94static struct bpf_object *bpf_object__new(const char *path)
95{
96 struct bpf_object *obj;
97
98 obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1);
99 if (!obj) {
100 pr_warning("alloc memory failed for %s\n", path);
101 return NULL;
102 }
103
104 strcpy(obj->path, path);
105 obj->efile.fd = -1;
106 return obj;
107}
108
109static void bpf_object__elf_finish(struct bpf_object *obj)
110{
111 if (!obj_elf_valid(obj))
112 return;
113
114 if (obj->efile.elf) {
115 elf_end(obj->efile.elf);
116 obj->efile.elf = NULL;
117 }
118 zclose(obj->efile.fd);
119}
120
121static int bpf_object__elf_init(struct bpf_object *obj)
122{
123 int err = 0;
124 GElf_Ehdr *ep;
125
126 if (obj_elf_valid(obj)) {
127 pr_warning("elf init: internal error\n");
128 return -EEXIST;
129 }
130
131 obj->efile.fd = open(obj->path, O_RDONLY);
132 if (obj->efile.fd < 0) {
133 pr_warning("failed to open %s: %s\n", obj->path,
134 strerror(errno));
135 return -errno;
136 }
137
138 obj->efile.elf = elf_begin(obj->efile.fd,
139 LIBBPF_ELF_C_READ_MMAP,
140 NULL);
141 if (!obj->efile.elf) {
142 pr_warning("failed to open %s as ELF file\n",
143 obj->path);
144 err = -EINVAL;
145 goto errout;
146 }
147
148 if (!gelf_getehdr(obj->efile.elf, &obj->efile.ehdr)) {
149 pr_warning("failed to get EHDR from %s\n",
150 obj->path);
151 err = -EINVAL;
152 goto errout;
153 }
154 ep = &obj->efile.ehdr;
155
156 if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) {
157 pr_warning("%s is not an eBPF object file\n",
158 obj->path);
159 err = -EINVAL;
160 goto errout;
161 }
162
163 return 0;
164errout:
165 bpf_object__elf_finish(obj);
166 return err;
167}
168
169static struct bpf_object *
170__bpf_object__open(const char *path)
171{
172 struct bpf_object *obj;
173
174 if (elf_version(EV_CURRENT) == EV_NONE) {
175 pr_warning("failed to init libelf for %s\n", path);
176 return NULL;
177 }
178
179 obj = bpf_object__new(path);
180 if (!obj)
181 return NULL;
182
183 if (bpf_object__elf_init(obj))
184 goto out;
185
186 bpf_object__elf_finish(obj);
187 return obj;
188out:
189 bpf_object__close(obj);
190 return NULL;
191}
192
193struct bpf_object *bpf_object__open(const char *path)
194{
195 /* param validation */
196 if (!path)
197 return NULL;
198
199 pr_debug("loading %s\n", path);
200
201 return __bpf_object__open(path);
202}
203
204void bpf_object__close(struct bpf_object *obj)
205{
206 if (!obj)
207 return;
208
209 bpf_object__elf_finish(obj);
210
211 free(obj);
212}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 8d1eebafa958..ec3301ceeb85 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -8,6 +8,8 @@
8#ifndef __BPF_LIBBPF_H 8#ifndef __BPF_LIBBPF_H
9#define __BPF_LIBBPF_H 9#define __BPF_LIBBPF_H
10 10
11#include <stdio.h>
12
11/* 13/*
12 * In include/linux/compiler-gcc.h, __printf is defined. However 14 * In include/linux/compiler-gcc.h, __printf is defined. However
13 * it should be better if libbpf.h doesn't depend on Linux header file. 15 * it should be better if libbpf.h doesn't depend on Linux header file.
@@ -20,4 +22,10 @@ void libbpf_set_print(libbpf_print_fn_t warn,
20 libbpf_print_fn_t info, 22 libbpf_print_fn_t info,
21 libbpf_print_fn_t debug); 23 libbpf_print_fn_t debug);
22 24
25/* Hide internal to user */
26struct bpf_object;
27
28struct bpf_object *bpf_object__open(const char *path);
29void bpf_object__close(struct bpf_object *object);
30
23#endif 31#endif