bpf tools: Collect version and license from ELF sections
[deliverable/linux.git] / tools / lib / bpf / libbpf.c
1 /*
2 * Common eBPF ELF object loading operations.
3 *
4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
6 * Copyright (C) 2015 Huawei Inc.
7 */
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <stdarg.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <fcntl.h>
15 #include <errno.h>
16 #include <asm/unistd.h>
17 #include <linux/kernel.h>
18 #include <linux/bpf.h>
19 #include <libelf.h>
20 #include <gelf.h>
21
22 #include "libbpf.h"
23
24 #define __printf(a, b) __attribute__((format(printf, a, b)))
25
26 __printf(1, 2)
27 static int __base_pr(const char *format, ...)
28 {
29 va_list args;
30 int err;
31
32 va_start(args, format);
33 err = vfprintf(stderr, format, args);
34 va_end(args);
35 return err;
36 }
37
38 static __printf(1, 2) libbpf_print_fn_t __pr_warning = __base_pr;
39 static __printf(1, 2) libbpf_print_fn_t __pr_info = __base_pr;
40 static __printf(1, 2) libbpf_print_fn_t __pr_debug;
41
42 #define __pr(func, fmt, ...) \
43 do { \
44 if ((func)) \
45 (func)("libbpf: " fmt, ##__VA_ARGS__); \
46 } while (0)
47
48 #define pr_warning(fmt, ...) __pr(__pr_warning, fmt, ##__VA_ARGS__)
49 #define pr_info(fmt, ...) __pr(__pr_info, fmt, ##__VA_ARGS__)
50 #define pr_debug(fmt, ...) __pr(__pr_debug, fmt, ##__VA_ARGS__)
51
52 void libbpf_set_print(libbpf_print_fn_t warn,
53 libbpf_print_fn_t info,
54 libbpf_print_fn_t debug)
55 {
56 __pr_warning = warn;
57 __pr_info = info;
58 __pr_debug = debug;
59 }
60
61 /* Copied from tools/perf/util/util.h */
62 #ifndef zfree
63 # define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
64 #endif
65
66 #ifndef zclose
67 # define zclose(fd) ({ \
68 int ___err = 0; \
69 if ((fd) >= 0) \
70 ___err = close((fd)); \
71 fd = -1; \
72 ___err; })
73 #endif
74
75 #ifdef HAVE_LIBELF_MMAP_SUPPORT
76 # define LIBBPF_ELF_C_READ_MMAP ELF_C_READ_MMAP
77 #else
78 # define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
79 #endif
80
81 struct bpf_object {
82 char license[64];
83 u32 kern_version;
84 /*
85 * Information when doing elf related work. Only valid if fd
86 * is valid.
87 */
88 struct {
89 int fd;
90 void *obj_buf;
91 size_t obj_buf_sz;
92 Elf *elf;
93 GElf_Ehdr ehdr;
94 } efile;
95 char path[];
96 };
97 #define obj_elf_valid(o) ((o)->efile.elf)
98
99 static struct bpf_object *bpf_object__new(const char *path,
100 void *obj_buf,
101 size_t obj_buf_sz)
102 {
103 struct bpf_object *obj;
104
105 obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1);
106 if (!obj) {
107 pr_warning("alloc memory failed for %s\n", path);
108 return NULL;
109 }
110
111 strcpy(obj->path, path);
112 obj->efile.fd = -1;
113
114 /*
115 * Caller of this function should also calls
116 * bpf_object__elf_finish() after data collection to return
117 * obj_buf to user. If not, we should duplicate the buffer to
118 * avoid user freeing them before elf finish.
119 */
120 obj->efile.obj_buf = obj_buf;
121 obj->efile.obj_buf_sz = obj_buf_sz;
122
123 return obj;
124 }
125
126 static void bpf_object__elf_finish(struct bpf_object *obj)
127 {
128 if (!obj_elf_valid(obj))
129 return;
130
131 if (obj->efile.elf) {
132 elf_end(obj->efile.elf);
133 obj->efile.elf = NULL;
134 }
135 zclose(obj->efile.fd);
136 obj->efile.obj_buf = NULL;
137 obj->efile.obj_buf_sz = 0;
138 }
139
140 static int bpf_object__elf_init(struct bpf_object *obj)
141 {
142 int err = 0;
143 GElf_Ehdr *ep;
144
145 if (obj_elf_valid(obj)) {
146 pr_warning("elf init: internal error\n");
147 return -EEXIST;
148 }
149
150 if (obj->efile.obj_buf_sz > 0) {
151 /*
152 * obj_buf should have been validated by
153 * bpf_object__open_buffer().
154 */
155 obj->efile.elf = elf_memory(obj->efile.obj_buf,
156 obj->efile.obj_buf_sz);
157 } else {
158 obj->efile.fd = open(obj->path, O_RDONLY);
159 if (obj->efile.fd < 0) {
160 pr_warning("failed to open %s: %s\n", obj->path,
161 strerror(errno));
162 return -errno;
163 }
164
165 obj->efile.elf = elf_begin(obj->efile.fd,
166 LIBBPF_ELF_C_READ_MMAP,
167 NULL);
168 }
169
170 if (!obj->efile.elf) {
171 pr_warning("failed to open %s as ELF file\n",
172 obj->path);
173 err = -EINVAL;
174 goto errout;
175 }
176
177 if (!gelf_getehdr(obj->efile.elf, &obj->efile.ehdr)) {
178 pr_warning("failed to get EHDR from %s\n",
179 obj->path);
180 err = -EINVAL;
181 goto errout;
182 }
183 ep = &obj->efile.ehdr;
184
185 if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) {
186 pr_warning("%s is not an eBPF object file\n",
187 obj->path);
188 err = -EINVAL;
189 goto errout;
190 }
191
192 return 0;
193 errout:
194 bpf_object__elf_finish(obj);
195 return err;
196 }
197
198 static int
199 bpf_object__check_endianness(struct bpf_object *obj)
200 {
201 static unsigned int const endian = 1;
202
203 switch (obj->efile.ehdr.e_ident[EI_DATA]) {
204 case ELFDATA2LSB:
205 /* We are big endian, BPF obj is little endian. */
206 if (*(unsigned char const *)&endian != 1)
207 goto mismatch;
208 break;
209
210 case ELFDATA2MSB:
211 /* We are little endian, BPF obj is big endian. */
212 if (*(unsigned char const *)&endian != 0)
213 goto mismatch;
214 break;
215 default:
216 return -EINVAL;
217 }
218
219 return 0;
220
221 mismatch:
222 pr_warning("Error: endianness mismatch.\n");
223 return -EINVAL;
224 }
225
226 static int
227 bpf_object__init_license(struct bpf_object *obj,
228 void *data, size_t size)
229 {
230 memcpy(obj->license, data,
231 min(size, sizeof(obj->license) - 1));
232 pr_debug("license of %s is %s\n", obj->path, obj->license);
233 return 0;
234 }
235
236 static int
237 bpf_object__init_kversion(struct bpf_object *obj,
238 void *data, size_t size)
239 {
240 u32 kver;
241
242 if (size != sizeof(kver)) {
243 pr_warning("invalid kver section in %s\n", obj->path);
244 return -EINVAL;
245 }
246 memcpy(&kver, data, sizeof(kver));
247 obj->kern_version = kver;
248 pr_debug("kernel version of %s is %x\n", obj->path,
249 obj->kern_version);
250 return 0;
251 }
252
253 static int bpf_object__elf_collect(struct bpf_object *obj)
254 {
255 Elf *elf = obj->efile.elf;
256 GElf_Ehdr *ep = &obj->efile.ehdr;
257 Elf_Scn *scn = NULL;
258 int idx = 0, err = 0;
259
260 /* Elf is corrupted/truncated, avoid calling elf_strptr. */
261 if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
262 pr_warning("failed to get e_shstrndx from %s\n",
263 obj->path);
264 return -EINVAL;
265 }
266
267 while ((scn = elf_nextscn(elf, scn)) != NULL) {
268 char *name;
269 GElf_Shdr sh;
270 Elf_Data *data;
271
272 idx++;
273 if (gelf_getshdr(scn, &sh) != &sh) {
274 pr_warning("failed to get section header from %s\n",
275 obj->path);
276 err = -EINVAL;
277 goto out;
278 }
279
280 name = elf_strptr(elf, ep->e_shstrndx, sh.sh_name);
281 if (!name) {
282 pr_warning("failed to get section name from %s\n",
283 obj->path);
284 err = -EINVAL;
285 goto out;
286 }
287
288 data = elf_getdata(scn, 0);
289 if (!data) {
290 pr_warning("failed to get section data from %s(%s)\n",
291 name, obj->path);
292 err = -EINVAL;
293 goto out;
294 }
295 pr_debug("section %s, size %ld, link %d, flags %lx, type=%d\n",
296 name, (unsigned long)data->d_size,
297 (int)sh.sh_link, (unsigned long)sh.sh_flags,
298 (int)sh.sh_type);
299
300 if (strcmp(name, "license") == 0)
301 err = bpf_object__init_license(obj,
302 data->d_buf,
303 data->d_size);
304 else if (strcmp(name, "version") == 0)
305 err = bpf_object__init_kversion(obj,
306 data->d_buf,
307 data->d_size);
308 if (err)
309 goto out;
310 }
311 out:
312 return err;
313 }
314
315 static int bpf_object__validate(struct bpf_object *obj)
316 {
317 if (obj->kern_version == 0) {
318 pr_warning("%s doesn't provide kernel version\n",
319 obj->path);
320 return -EINVAL;
321 }
322 return 0;
323 }
324
325 static struct bpf_object *
326 __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz)
327 {
328 struct bpf_object *obj;
329
330 if (elf_version(EV_CURRENT) == EV_NONE) {
331 pr_warning("failed to init libelf for %s\n", path);
332 return NULL;
333 }
334
335 obj = bpf_object__new(path, obj_buf, obj_buf_sz);
336 if (!obj)
337 return NULL;
338
339 if (bpf_object__elf_init(obj))
340 goto out;
341 if (bpf_object__check_endianness(obj))
342 goto out;
343 if (bpf_object__elf_collect(obj))
344 goto out;
345 if (bpf_object__validate(obj))
346 goto out;
347
348 bpf_object__elf_finish(obj);
349 return obj;
350 out:
351 bpf_object__close(obj);
352 return NULL;
353 }
354
355 struct bpf_object *bpf_object__open(const char *path)
356 {
357 /* param validation */
358 if (!path)
359 return NULL;
360
361 pr_debug("loading %s\n", path);
362
363 return __bpf_object__open(path, NULL, 0);
364 }
365
366 struct bpf_object *bpf_object__open_buffer(void *obj_buf,
367 size_t obj_buf_sz)
368 {
369 /* param validation */
370 if (!obj_buf || obj_buf_sz <= 0)
371 return NULL;
372
373 pr_debug("loading object from buffer\n");
374
375 return __bpf_object__open("[buffer]", obj_buf, obj_buf_sz);
376 }
377
378 void bpf_object__close(struct bpf_object *obj)
379 {
380 if (!obj)
381 return;
382
383 bpf_object__elf_finish(obj);
384
385 free(obj);
386 }
This page took 0.045225 seconds and 5 git commands to generate.