blob: 102156f322b6f2ae14eaac803c761ee02c59375a [file] [log] [blame]
Wang Nan1b76c132015-07-01 02:13:51 +00001/*
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>
Wang Nanb3f59d62015-07-01 02:13:52 +000010#include <stdio.h>
11#include <stdarg.h>
12#include <string.h>
Wang Nan1b76c132015-07-01 02:13:51 +000013#include <unistd.h>
Wang Nan1a5e3fb2015-07-01 02:13:53 +000014#include <fcntl.h>
15#include <errno.h>
Wang Nan1b76c132015-07-01 02:13:51 +000016#include <asm/unistd.h>
Wang Nancb1e5e92015-07-01 02:13:57 +000017#include <linux/kernel.h>
Wang Nan1b76c132015-07-01 02:13:51 +000018#include <linux/bpf.h>
Wang Nan1a5e3fb2015-07-01 02:13:53 +000019#include <libelf.h>
20#include <gelf.h>
Wang Nan1b76c132015-07-01 02:13:51 +000021
22#include "libbpf.h"
Wang Nanb3f59d62015-07-01 02:13:52 +000023
24#define __printf(a, b) __attribute__((format(printf, a, b)))
25
26__printf(1, 2)
27static 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
38static __printf(1, 2) libbpf_print_fn_t __pr_warning = __base_pr;
39static __printf(1, 2) libbpf_print_fn_t __pr_info = __base_pr;
40static __printf(1, 2) libbpf_print_fn_t __pr_debug;
41
42#define __pr(func, fmt, ...) \
43do { \
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
52void 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}
Wang Nan1a5e3fb2015-07-01 02:13:53 +000060
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
Wang Nana5b8bd42015-07-01 02:14:00 +000081/*
82 * bpf_prog should be a better name but it has been used in
83 * linux/filter.h.
84 */
85struct bpf_program {
86 /* Index in elf obj file, for relocation use. */
87 int idx;
88 char *section_name;
89 struct bpf_insn *insns;
90 size_t insns_cnt;
91};
92
Wang Nan1a5e3fb2015-07-01 02:13:53 +000093struct bpf_object {
Wang Nancb1e5e92015-07-01 02:13:57 +000094 char license[64];
95 u32 kern_version;
Wang Nan0b3d1ef2015-07-01 02:13:58 +000096 void *maps_buf;
97 size_t maps_buf_sz;
98
Wang Nana5b8bd42015-07-01 02:14:00 +000099 struct bpf_program *programs;
100 size_t nr_programs;
101
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000102 /*
103 * Information when doing elf related work. Only valid if fd
104 * is valid.
105 */
106 struct {
107 int fd;
Wang Nan6c956392015-07-01 02:13:54 +0000108 void *obj_buf;
109 size_t obj_buf_sz;
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000110 Elf *elf;
111 GElf_Ehdr ehdr;
Wang Nanbec7d682015-07-01 02:13:59 +0000112 Elf_Data *symbols;
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000113 } efile;
114 char path[];
115};
116#define obj_elf_valid(o) ((o)->efile.elf)
117
Wang Nana5b8bd42015-07-01 02:14:00 +0000118static void bpf_program__exit(struct bpf_program *prog)
119{
120 if (!prog)
121 return;
122
123 zfree(&prog->section_name);
124 zfree(&prog->insns);
125 prog->insns_cnt = 0;
126 prog->idx = -1;
127}
128
129static int
130bpf_program__init(void *data, size_t size, char *name, int idx,
131 struct bpf_program *prog)
132{
133 if (size < sizeof(struct bpf_insn)) {
134 pr_warning("corrupted section '%s'\n", name);
135 return -EINVAL;
136 }
137
138 bzero(prog, sizeof(*prog));
139
140 prog->section_name = strdup(name);
141 if (!prog->section_name) {
142 pr_warning("failed to alloc name for prog %s\n",
143 name);
144 goto errout;
145 }
146
147 prog->insns = malloc(size);
148 if (!prog->insns) {
149 pr_warning("failed to alloc insns for %s\n", name);
150 goto errout;
151 }
152 prog->insns_cnt = size / sizeof(struct bpf_insn);
153 memcpy(prog->insns, data,
154 prog->insns_cnt * sizeof(struct bpf_insn));
155 prog->idx = idx;
156
157 return 0;
158errout:
159 bpf_program__exit(prog);
160 return -ENOMEM;
161}
162
163static int
164bpf_object__add_program(struct bpf_object *obj, void *data, size_t size,
165 char *name, int idx)
166{
167 struct bpf_program prog, *progs;
168 int nr_progs, err;
169
170 err = bpf_program__init(data, size, name, idx, &prog);
171 if (err)
172 return err;
173
174 progs = obj->programs;
175 nr_progs = obj->nr_programs;
176
177 progs = realloc(progs, sizeof(progs[0]) * (nr_progs + 1));
178 if (!progs) {
179 /*
180 * In this case the original obj->programs
181 * is still valid, so don't need special treat for
182 * bpf_close_object().
183 */
184 pr_warning("failed to alloc a new program '%s'\n",
185 name);
186 bpf_program__exit(&prog);
187 return -ENOMEM;
188 }
189
190 pr_debug("found program %s\n", prog.section_name);
191 obj->programs = progs;
192 obj->nr_programs = nr_progs + 1;
193 progs[nr_progs] = prog;
194 return 0;
195}
196
Wang Nan6c956392015-07-01 02:13:54 +0000197static struct bpf_object *bpf_object__new(const char *path,
198 void *obj_buf,
199 size_t obj_buf_sz)
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000200{
201 struct bpf_object *obj;
202
203 obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1);
204 if (!obj) {
205 pr_warning("alloc memory failed for %s\n", path);
206 return NULL;
207 }
208
209 strcpy(obj->path, path);
210 obj->efile.fd = -1;
Wang Nan6c956392015-07-01 02:13:54 +0000211
212 /*
213 * Caller of this function should also calls
214 * bpf_object__elf_finish() after data collection to return
215 * obj_buf to user. If not, we should duplicate the buffer to
216 * avoid user freeing them before elf finish.
217 */
218 obj->efile.obj_buf = obj_buf;
219 obj->efile.obj_buf_sz = obj_buf_sz;
220
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000221 return obj;
222}
223
224static void bpf_object__elf_finish(struct bpf_object *obj)
225{
226 if (!obj_elf_valid(obj))
227 return;
228
229 if (obj->efile.elf) {
230 elf_end(obj->efile.elf);
231 obj->efile.elf = NULL;
232 }
Wang Nanbec7d682015-07-01 02:13:59 +0000233 obj->efile.symbols = NULL;
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000234 zclose(obj->efile.fd);
Wang Nan6c956392015-07-01 02:13:54 +0000235 obj->efile.obj_buf = NULL;
236 obj->efile.obj_buf_sz = 0;
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000237}
238
239static int bpf_object__elf_init(struct bpf_object *obj)
240{
241 int err = 0;
242 GElf_Ehdr *ep;
243
244 if (obj_elf_valid(obj)) {
245 pr_warning("elf init: internal error\n");
246 return -EEXIST;
247 }
248
Wang Nan6c956392015-07-01 02:13:54 +0000249 if (obj->efile.obj_buf_sz > 0) {
250 /*
251 * obj_buf should have been validated by
252 * bpf_object__open_buffer().
253 */
254 obj->efile.elf = elf_memory(obj->efile.obj_buf,
255 obj->efile.obj_buf_sz);
256 } else {
257 obj->efile.fd = open(obj->path, O_RDONLY);
258 if (obj->efile.fd < 0) {
259 pr_warning("failed to open %s: %s\n", obj->path,
260 strerror(errno));
261 return -errno;
262 }
263
264 obj->efile.elf = elf_begin(obj->efile.fd,
265 LIBBPF_ELF_C_READ_MMAP,
266 NULL);
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000267 }
268
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000269 if (!obj->efile.elf) {
270 pr_warning("failed to open %s as ELF file\n",
271 obj->path);
272 err = -EINVAL;
273 goto errout;
274 }
275
276 if (!gelf_getehdr(obj->efile.elf, &obj->efile.ehdr)) {
277 pr_warning("failed to get EHDR from %s\n",
278 obj->path);
279 err = -EINVAL;
280 goto errout;
281 }
282 ep = &obj->efile.ehdr;
283
284 if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) {
285 pr_warning("%s is not an eBPF object file\n",
286 obj->path);
287 err = -EINVAL;
288 goto errout;
289 }
290
291 return 0;
292errout:
293 bpf_object__elf_finish(obj);
294 return err;
295}
296
Wang Nancc4228d2015-07-01 02:13:55 +0000297static int
298bpf_object__check_endianness(struct bpf_object *obj)
299{
300 static unsigned int const endian = 1;
301
302 switch (obj->efile.ehdr.e_ident[EI_DATA]) {
303 case ELFDATA2LSB:
304 /* We are big endian, BPF obj is little endian. */
305 if (*(unsigned char const *)&endian != 1)
306 goto mismatch;
307 break;
308
309 case ELFDATA2MSB:
310 /* We are little endian, BPF obj is big endian. */
311 if (*(unsigned char const *)&endian != 0)
312 goto mismatch;
313 break;
314 default:
315 return -EINVAL;
316 }
317
318 return 0;
319
320mismatch:
321 pr_warning("Error: endianness mismatch.\n");
322 return -EINVAL;
323}
324
Wang Nancb1e5e92015-07-01 02:13:57 +0000325static int
326bpf_object__init_license(struct bpf_object *obj,
327 void *data, size_t size)
328{
329 memcpy(obj->license, data,
330 min(size, sizeof(obj->license) - 1));
331 pr_debug("license of %s is %s\n", obj->path, obj->license);
332 return 0;
333}
334
335static int
336bpf_object__init_kversion(struct bpf_object *obj,
337 void *data, size_t size)
338{
339 u32 kver;
340
341 if (size != sizeof(kver)) {
342 pr_warning("invalid kver section in %s\n", obj->path);
343 return -EINVAL;
344 }
345 memcpy(&kver, data, sizeof(kver));
346 obj->kern_version = kver;
347 pr_debug("kernel version of %s is %x\n", obj->path,
348 obj->kern_version);
349 return 0;
350}
351
Wang Nan0b3d1ef2015-07-01 02:13:58 +0000352static int
353bpf_object__init_maps(struct bpf_object *obj, void *data,
354 size_t size)
355{
356 if (size == 0) {
357 pr_debug("%s doesn't need map definition\n",
358 obj->path);
359 return 0;
360 }
361
362 obj->maps_buf = malloc(size);
363 if (!obj->maps_buf) {
364 pr_warning("malloc maps failed: %s\n", obj->path);
365 return -ENOMEM;
366 }
367
368 obj->maps_buf_sz = size;
369 memcpy(obj->maps_buf, data, size);
370 pr_debug("maps in %s: %ld bytes\n", obj->path, (long)size);
371 return 0;
372}
373
Wang Nan29603662015-07-01 02:13:56 +0000374static int bpf_object__elf_collect(struct bpf_object *obj)
375{
376 Elf *elf = obj->efile.elf;
377 GElf_Ehdr *ep = &obj->efile.ehdr;
378 Elf_Scn *scn = NULL;
379 int idx = 0, err = 0;
380
381 /* Elf is corrupted/truncated, avoid calling elf_strptr. */
382 if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
383 pr_warning("failed to get e_shstrndx from %s\n",
384 obj->path);
385 return -EINVAL;
386 }
387
388 while ((scn = elf_nextscn(elf, scn)) != NULL) {
389 char *name;
390 GElf_Shdr sh;
391 Elf_Data *data;
392
393 idx++;
394 if (gelf_getshdr(scn, &sh) != &sh) {
395 pr_warning("failed to get section header from %s\n",
396 obj->path);
397 err = -EINVAL;
398 goto out;
399 }
400
401 name = elf_strptr(elf, ep->e_shstrndx, sh.sh_name);
402 if (!name) {
403 pr_warning("failed to get section name from %s\n",
404 obj->path);
405 err = -EINVAL;
406 goto out;
407 }
408
409 data = elf_getdata(scn, 0);
410 if (!data) {
411 pr_warning("failed to get section data from %s(%s)\n",
412 name, obj->path);
413 err = -EINVAL;
414 goto out;
415 }
416 pr_debug("section %s, size %ld, link %d, flags %lx, type=%d\n",
417 name, (unsigned long)data->d_size,
418 (int)sh.sh_link, (unsigned long)sh.sh_flags,
419 (int)sh.sh_type);
Wang Nancb1e5e92015-07-01 02:13:57 +0000420
421 if (strcmp(name, "license") == 0)
422 err = bpf_object__init_license(obj,
423 data->d_buf,
424 data->d_size);
425 else if (strcmp(name, "version") == 0)
426 err = bpf_object__init_kversion(obj,
427 data->d_buf,
428 data->d_size);
Wang Nan0b3d1ef2015-07-01 02:13:58 +0000429 else if (strcmp(name, "maps") == 0)
430 err = bpf_object__init_maps(obj, data->d_buf,
431 data->d_size);
Wang Nanbec7d682015-07-01 02:13:59 +0000432 else if (sh.sh_type == SHT_SYMTAB) {
433 if (obj->efile.symbols) {
434 pr_warning("bpf: multiple SYMTAB in %s\n",
435 obj->path);
436 err = -EEXIST;
437 } else
438 obj->efile.symbols = data;
Wang Nana5b8bd42015-07-01 02:14:00 +0000439 } else if ((sh.sh_type == SHT_PROGBITS) &&
440 (sh.sh_flags & SHF_EXECINSTR) &&
441 (data->d_size > 0)) {
442 err = bpf_object__add_program(obj, data->d_buf,
443 data->d_size, name, idx);
444 if (err) {
445 char errmsg[128];
446 strerror_r(-err, errmsg, sizeof(errmsg));
447 pr_warning("failed to alloc program %s (%s): %s",
448 name, obj->path, errmsg);
449 }
Wang Nanbec7d682015-07-01 02:13:59 +0000450 }
Wang Nancb1e5e92015-07-01 02:13:57 +0000451 if (err)
452 goto out;
Wang Nan29603662015-07-01 02:13:56 +0000453 }
454out:
455 return err;
456}
457
Wang Nancb1e5e92015-07-01 02:13:57 +0000458static int bpf_object__validate(struct bpf_object *obj)
459{
460 if (obj->kern_version == 0) {
461 pr_warning("%s doesn't provide kernel version\n",
462 obj->path);
463 return -EINVAL;
464 }
465 return 0;
466}
467
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000468static struct bpf_object *
Wang Nan6c956392015-07-01 02:13:54 +0000469__bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz)
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000470{
471 struct bpf_object *obj;
472
473 if (elf_version(EV_CURRENT) == EV_NONE) {
474 pr_warning("failed to init libelf for %s\n", path);
475 return NULL;
476 }
477
Wang Nan6c956392015-07-01 02:13:54 +0000478 obj = bpf_object__new(path, obj_buf, obj_buf_sz);
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000479 if (!obj)
480 return NULL;
481
482 if (bpf_object__elf_init(obj))
483 goto out;
Wang Nancc4228d2015-07-01 02:13:55 +0000484 if (bpf_object__check_endianness(obj))
485 goto out;
Wang Nan29603662015-07-01 02:13:56 +0000486 if (bpf_object__elf_collect(obj))
487 goto out;
Wang Nancb1e5e92015-07-01 02:13:57 +0000488 if (bpf_object__validate(obj))
489 goto out;
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000490
491 bpf_object__elf_finish(obj);
492 return obj;
493out:
494 bpf_object__close(obj);
495 return NULL;
496}
497
498struct bpf_object *bpf_object__open(const char *path)
499{
500 /* param validation */
501 if (!path)
502 return NULL;
503
504 pr_debug("loading %s\n", path);
505
Wang Nan6c956392015-07-01 02:13:54 +0000506 return __bpf_object__open(path, NULL, 0);
507}
508
509struct bpf_object *bpf_object__open_buffer(void *obj_buf,
510 size_t obj_buf_sz)
511{
512 /* param validation */
513 if (!obj_buf || obj_buf_sz <= 0)
514 return NULL;
515
516 pr_debug("loading object from buffer\n");
517
518 return __bpf_object__open("[buffer]", obj_buf, obj_buf_sz);
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000519}
520
521void bpf_object__close(struct bpf_object *obj)
522{
Wang Nana5b8bd42015-07-01 02:14:00 +0000523 size_t i;
524
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000525 if (!obj)
526 return;
527
528 bpf_object__elf_finish(obj);
529
Wang Nan0b3d1ef2015-07-01 02:13:58 +0000530 zfree(&obj->maps_buf);
Wang Nana5b8bd42015-07-01 02:14:00 +0000531
532 if (obj->programs && obj->nr_programs) {
533 for (i = 0; i < obj->nr_programs; i++)
534 bpf_program__exit(&obj->programs[i]);
535 }
536 zfree(&obj->programs);
537
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000538 free(obj);
539}