bpf tools: Introduce bpf_load_program() to bpf.c
[deliverable/linux.git] / tools / lib / bpf / libbpf.c
CommitLineData
1b76c13e
WN
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>
b3f59d66
WN
10#include <stdio.h>
11#include <stdarg.h>
34090915 12#include <inttypes.h>
b3f59d66 13#include <string.h>
1b76c13e 14#include <unistd.h>
1a5e3fb1
WN
15#include <fcntl.h>
16#include <errno.h>
1b76c13e 17#include <asm/unistd.h>
cb1e5e96 18#include <linux/kernel.h>
1b76c13e 19#include <linux/bpf.h>
1a5e3fb1
WN
20#include <libelf.h>
21#include <gelf.h>
1b76c13e
WN
22
23#include "libbpf.h"
52d3352e 24#include "bpf.h"
b3f59d66
WN
25
26#define __printf(a, b) __attribute__((format(printf, a, b)))
27
28__printf(1, 2)
29static int __base_pr(const char *format, ...)
30{
31 va_list args;
32 int err;
33
34 va_start(args, format);
35 err = vfprintf(stderr, format, args);
36 va_end(args);
37 return err;
38}
39
40static __printf(1, 2) libbpf_print_fn_t __pr_warning = __base_pr;
41static __printf(1, 2) libbpf_print_fn_t __pr_info = __base_pr;
42static __printf(1, 2) libbpf_print_fn_t __pr_debug;
43
44#define __pr(func, fmt, ...) \
45do { \
46 if ((func)) \
47 (func)("libbpf: " fmt, ##__VA_ARGS__); \
48} while (0)
49
50#define pr_warning(fmt, ...) __pr(__pr_warning, fmt, ##__VA_ARGS__)
51#define pr_info(fmt, ...) __pr(__pr_info, fmt, ##__VA_ARGS__)
52#define pr_debug(fmt, ...) __pr(__pr_debug, fmt, ##__VA_ARGS__)
53
54void libbpf_set_print(libbpf_print_fn_t warn,
55 libbpf_print_fn_t info,
56 libbpf_print_fn_t debug)
57{
58 __pr_warning = warn;
59 __pr_info = info;
60 __pr_debug = debug;
61}
1a5e3fb1
WN
62
63/* Copied from tools/perf/util/util.h */
64#ifndef zfree
65# define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
66#endif
67
68#ifndef zclose
69# define zclose(fd) ({ \
70 int ___err = 0; \
71 if ((fd) >= 0) \
72 ___err = close((fd)); \
73 fd = -1; \
74 ___err; })
75#endif
76
77#ifdef HAVE_LIBELF_MMAP_SUPPORT
78# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ_MMAP
79#else
80# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
81#endif
82
a5b8bd47
WN
83/*
84 * bpf_prog should be a better name but it has been used in
85 * linux/filter.h.
86 */
87struct bpf_program {
88 /* Index in elf obj file, for relocation use. */
89 int idx;
90 char *section_name;
91 struct bpf_insn *insns;
92 size_t insns_cnt;
34090915
WN
93
94 struct {
95 int insn_idx;
96 int map_idx;
97 } *reloc_desc;
98 int nr_reloc;
a5b8bd47
WN
99};
100
1a5e3fb1 101struct bpf_object {
cb1e5e96
WN
102 char license[64];
103 u32 kern_version;
0b3d1efa
WN
104 void *maps_buf;
105 size_t maps_buf_sz;
106
a5b8bd47
WN
107 struct bpf_program *programs;
108 size_t nr_programs;
52d3352e
WN
109 int *map_fds;
110 /*
111 * This field is required because maps_buf will be freed and
112 * maps_buf_sz will be set to 0 after loaded.
113 */
114 size_t nr_map_fds;
115 bool loaded;
a5b8bd47 116
1a5e3fb1
WN
117 /*
118 * Information when doing elf related work. Only valid if fd
119 * is valid.
120 */
121 struct {
122 int fd;
6c956392
WN
123 void *obj_buf;
124 size_t obj_buf_sz;
1a5e3fb1
WN
125 Elf *elf;
126 GElf_Ehdr ehdr;
bec7d68c 127 Elf_Data *symbols;
b62f06e8
WN
128 struct {
129 GElf_Shdr shdr;
130 Elf_Data *data;
131 } *reloc;
132 int nr_reloc;
1a5e3fb1
WN
133 } efile;
134 char path[];
135};
136#define obj_elf_valid(o) ((o)->efile.elf)
137
a5b8bd47
WN
138static void bpf_program__exit(struct bpf_program *prog)
139{
140 if (!prog)
141 return;
142
143 zfree(&prog->section_name);
144 zfree(&prog->insns);
34090915
WN
145 zfree(&prog->reloc_desc);
146
147 prog->nr_reloc = 0;
a5b8bd47
WN
148 prog->insns_cnt = 0;
149 prog->idx = -1;
150}
151
152static int
153bpf_program__init(void *data, size_t size, char *name, int idx,
154 struct bpf_program *prog)
155{
156 if (size < sizeof(struct bpf_insn)) {
157 pr_warning("corrupted section '%s'\n", name);
158 return -EINVAL;
159 }
160
161 bzero(prog, sizeof(*prog));
162
163 prog->section_name = strdup(name);
164 if (!prog->section_name) {
165 pr_warning("failed to alloc name for prog %s\n",
166 name);
167 goto errout;
168 }
169
170 prog->insns = malloc(size);
171 if (!prog->insns) {
172 pr_warning("failed to alloc insns for %s\n", name);
173 goto errout;
174 }
175 prog->insns_cnt = size / sizeof(struct bpf_insn);
176 memcpy(prog->insns, data,
177 prog->insns_cnt * sizeof(struct bpf_insn));
178 prog->idx = idx;
179
180 return 0;
181errout:
182 bpf_program__exit(prog);
183 return -ENOMEM;
184}
185
186static int
187bpf_object__add_program(struct bpf_object *obj, void *data, size_t size,
188 char *name, int idx)
189{
190 struct bpf_program prog, *progs;
191 int nr_progs, err;
192
193 err = bpf_program__init(data, size, name, idx, &prog);
194 if (err)
195 return err;
196
197 progs = obj->programs;
198 nr_progs = obj->nr_programs;
199
200 progs = realloc(progs, sizeof(progs[0]) * (nr_progs + 1));
201 if (!progs) {
202 /*
203 * In this case the original obj->programs
204 * is still valid, so don't need special treat for
205 * bpf_close_object().
206 */
207 pr_warning("failed to alloc a new program '%s'\n",
208 name);
209 bpf_program__exit(&prog);
210 return -ENOMEM;
211 }
212
213 pr_debug("found program %s\n", prog.section_name);
214 obj->programs = progs;
215 obj->nr_programs = nr_progs + 1;
216 progs[nr_progs] = prog;
217 return 0;
218}
219
6c956392
WN
220static struct bpf_object *bpf_object__new(const char *path,
221 void *obj_buf,
222 size_t obj_buf_sz)
1a5e3fb1
WN
223{
224 struct bpf_object *obj;
225
226 obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1);
227 if (!obj) {
228 pr_warning("alloc memory failed for %s\n", path);
229 return NULL;
230 }
231
232 strcpy(obj->path, path);
233 obj->efile.fd = -1;
6c956392
WN
234
235 /*
236 * Caller of this function should also calls
237 * bpf_object__elf_finish() after data collection to return
238 * obj_buf to user. If not, we should duplicate the buffer to
239 * avoid user freeing them before elf finish.
240 */
241 obj->efile.obj_buf = obj_buf;
242 obj->efile.obj_buf_sz = obj_buf_sz;
243
52d3352e 244 obj->loaded = false;
1a5e3fb1
WN
245 return obj;
246}
247
248static void bpf_object__elf_finish(struct bpf_object *obj)
249{
250 if (!obj_elf_valid(obj))
251 return;
252
253 if (obj->efile.elf) {
254 elf_end(obj->efile.elf);
255 obj->efile.elf = NULL;
256 }
bec7d68c 257 obj->efile.symbols = NULL;
b62f06e8
WN
258
259 zfree(&obj->efile.reloc);
260 obj->efile.nr_reloc = 0;
1a5e3fb1 261 zclose(obj->efile.fd);
6c956392
WN
262 obj->efile.obj_buf = NULL;
263 obj->efile.obj_buf_sz = 0;
1a5e3fb1
WN
264}
265
266static int bpf_object__elf_init(struct bpf_object *obj)
267{
268 int err = 0;
269 GElf_Ehdr *ep;
270
271 if (obj_elf_valid(obj)) {
272 pr_warning("elf init: internal error\n");
273 return -EEXIST;
274 }
275
6c956392
WN
276 if (obj->efile.obj_buf_sz > 0) {
277 /*
278 * obj_buf should have been validated by
279 * bpf_object__open_buffer().
280 */
281 obj->efile.elf = elf_memory(obj->efile.obj_buf,
282 obj->efile.obj_buf_sz);
283 } else {
284 obj->efile.fd = open(obj->path, O_RDONLY);
285 if (obj->efile.fd < 0) {
286 pr_warning("failed to open %s: %s\n", obj->path,
287 strerror(errno));
288 return -errno;
289 }
290
291 obj->efile.elf = elf_begin(obj->efile.fd,
292 LIBBPF_ELF_C_READ_MMAP,
293 NULL);
1a5e3fb1
WN
294 }
295
1a5e3fb1
WN
296 if (!obj->efile.elf) {
297 pr_warning("failed to open %s as ELF file\n",
298 obj->path);
299 err = -EINVAL;
300 goto errout;
301 }
302
303 if (!gelf_getehdr(obj->efile.elf, &obj->efile.ehdr)) {
304 pr_warning("failed to get EHDR from %s\n",
305 obj->path);
306 err = -EINVAL;
307 goto errout;
308 }
309 ep = &obj->efile.ehdr;
310
311 if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) {
312 pr_warning("%s is not an eBPF object file\n",
313 obj->path);
314 err = -EINVAL;
315 goto errout;
316 }
317
318 return 0;
319errout:
320 bpf_object__elf_finish(obj);
321 return err;
322}
323
cc4228d5
WN
324static int
325bpf_object__check_endianness(struct bpf_object *obj)
326{
327 static unsigned int const endian = 1;
328
329 switch (obj->efile.ehdr.e_ident[EI_DATA]) {
330 case ELFDATA2LSB:
331 /* We are big endian, BPF obj is little endian. */
332 if (*(unsigned char const *)&endian != 1)
333 goto mismatch;
334 break;
335
336 case ELFDATA2MSB:
337 /* We are little endian, BPF obj is big endian. */
338 if (*(unsigned char const *)&endian != 0)
339 goto mismatch;
340 break;
341 default:
342 return -EINVAL;
343 }
344
345 return 0;
346
347mismatch:
348 pr_warning("Error: endianness mismatch.\n");
349 return -EINVAL;
350}
351
cb1e5e96
WN
352static int
353bpf_object__init_license(struct bpf_object *obj,
354 void *data, size_t size)
355{
356 memcpy(obj->license, data,
357 min(size, sizeof(obj->license) - 1));
358 pr_debug("license of %s is %s\n", obj->path, obj->license);
359 return 0;
360}
361
362static int
363bpf_object__init_kversion(struct bpf_object *obj,
364 void *data, size_t size)
365{
366 u32 kver;
367
368 if (size != sizeof(kver)) {
369 pr_warning("invalid kver section in %s\n", obj->path);
370 return -EINVAL;
371 }
372 memcpy(&kver, data, sizeof(kver));
373 obj->kern_version = kver;
374 pr_debug("kernel version of %s is %x\n", obj->path,
375 obj->kern_version);
376 return 0;
377}
378
0b3d1efa
WN
379static int
380bpf_object__init_maps(struct bpf_object *obj, void *data,
381 size_t size)
382{
383 if (size == 0) {
384 pr_debug("%s doesn't need map definition\n",
385 obj->path);
386 return 0;
387 }
388
389 obj->maps_buf = malloc(size);
390 if (!obj->maps_buf) {
391 pr_warning("malloc maps failed: %s\n", obj->path);
392 return -ENOMEM;
393 }
394
395 obj->maps_buf_sz = size;
396 memcpy(obj->maps_buf, data, size);
397 pr_debug("maps in %s: %ld bytes\n", obj->path, (long)size);
398 return 0;
399}
400
29603665
WN
401static int bpf_object__elf_collect(struct bpf_object *obj)
402{
403 Elf *elf = obj->efile.elf;
404 GElf_Ehdr *ep = &obj->efile.ehdr;
405 Elf_Scn *scn = NULL;
406 int idx = 0, err = 0;
407
408 /* Elf is corrupted/truncated, avoid calling elf_strptr. */
409 if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
410 pr_warning("failed to get e_shstrndx from %s\n",
411 obj->path);
412 return -EINVAL;
413 }
414
415 while ((scn = elf_nextscn(elf, scn)) != NULL) {
416 char *name;
417 GElf_Shdr sh;
418 Elf_Data *data;
419
420 idx++;
421 if (gelf_getshdr(scn, &sh) != &sh) {
422 pr_warning("failed to get section header from %s\n",
423 obj->path);
424 err = -EINVAL;
425 goto out;
426 }
427
428 name = elf_strptr(elf, ep->e_shstrndx, sh.sh_name);
429 if (!name) {
430 pr_warning("failed to get section name from %s\n",
431 obj->path);
432 err = -EINVAL;
433 goto out;
434 }
435
436 data = elf_getdata(scn, 0);
437 if (!data) {
438 pr_warning("failed to get section data from %s(%s)\n",
439 name, obj->path);
440 err = -EINVAL;
441 goto out;
442 }
443 pr_debug("section %s, size %ld, link %d, flags %lx, type=%d\n",
444 name, (unsigned long)data->d_size,
445 (int)sh.sh_link, (unsigned long)sh.sh_flags,
446 (int)sh.sh_type);
cb1e5e96
WN
447
448 if (strcmp(name, "license") == 0)
449 err = bpf_object__init_license(obj,
450 data->d_buf,
451 data->d_size);
452 else if (strcmp(name, "version") == 0)
453 err = bpf_object__init_kversion(obj,
454 data->d_buf,
455 data->d_size);
0b3d1efa
WN
456 else if (strcmp(name, "maps") == 0)
457 err = bpf_object__init_maps(obj, data->d_buf,
458 data->d_size);
bec7d68c
WN
459 else if (sh.sh_type == SHT_SYMTAB) {
460 if (obj->efile.symbols) {
461 pr_warning("bpf: multiple SYMTAB in %s\n",
462 obj->path);
463 err = -EEXIST;
464 } else
465 obj->efile.symbols = data;
a5b8bd47
WN
466 } else if ((sh.sh_type == SHT_PROGBITS) &&
467 (sh.sh_flags & SHF_EXECINSTR) &&
468 (data->d_size > 0)) {
469 err = bpf_object__add_program(obj, data->d_buf,
470 data->d_size, name, idx);
471 if (err) {
472 char errmsg[128];
473 strerror_r(-err, errmsg, sizeof(errmsg));
474 pr_warning("failed to alloc program %s (%s): %s",
475 name, obj->path, errmsg);
476 }
b62f06e8
WN
477 } else if (sh.sh_type == SHT_REL) {
478 void *reloc = obj->efile.reloc;
479 int nr_reloc = obj->efile.nr_reloc + 1;
480
481 reloc = realloc(reloc,
482 sizeof(*obj->efile.reloc) * nr_reloc);
483 if (!reloc) {
484 pr_warning("realloc failed\n");
485 err = -ENOMEM;
486 } else {
487 int n = nr_reloc - 1;
488
489 obj->efile.reloc = reloc;
490 obj->efile.nr_reloc = nr_reloc;
491
492 obj->efile.reloc[n].shdr = sh;
493 obj->efile.reloc[n].data = data;
494 }
bec7d68c 495 }
cb1e5e96
WN
496 if (err)
497 goto out;
29603665
WN
498 }
499out:
500 return err;
501}
502
34090915
WN
503static struct bpf_program *
504bpf_object__find_prog_by_idx(struct bpf_object *obj, int idx)
505{
506 struct bpf_program *prog;
507 size_t i;
508
509 for (i = 0; i < obj->nr_programs; i++) {
510 prog = &obj->programs[i];
511 if (prog->idx == idx)
512 return prog;
513 }
514 return NULL;
515}
516
517static int
518bpf_program__collect_reloc(struct bpf_program *prog,
519 size_t nr_maps, GElf_Shdr *shdr,
520 Elf_Data *data, Elf_Data *symbols)
521{
522 int i, nrels;
523
524 pr_debug("collecting relocating info for: '%s'\n",
525 prog->section_name);
526 nrels = shdr->sh_size / shdr->sh_entsize;
527
528 prog->reloc_desc = malloc(sizeof(*prog->reloc_desc) * nrels);
529 if (!prog->reloc_desc) {
530 pr_warning("failed to alloc memory in relocation\n");
531 return -ENOMEM;
532 }
533 prog->nr_reloc = nrels;
534
535 for (i = 0; i < nrels; i++) {
536 GElf_Sym sym;
537 GElf_Rel rel;
538 unsigned int insn_idx;
539 struct bpf_insn *insns = prog->insns;
540 size_t map_idx;
541
542 if (!gelf_getrel(data, i, &rel)) {
543 pr_warning("relocation: failed to get %d reloc\n", i);
544 return -EINVAL;
545 }
546
547 insn_idx = rel.r_offset / sizeof(struct bpf_insn);
548 pr_debug("relocation: insn_idx=%u\n", insn_idx);
549
550 if (!gelf_getsym(symbols,
551 GELF_R_SYM(rel.r_info),
552 &sym)) {
553 pr_warning("relocation: symbol %"PRIx64" not found\n",
554 GELF_R_SYM(rel.r_info));
555 return -EINVAL;
556 }
557
558 if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) {
559 pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n",
560 insn_idx, insns[insn_idx].code);
561 return -EINVAL;
562 }
563
564 map_idx = sym.st_value / sizeof(struct bpf_map_def);
565 if (map_idx >= nr_maps) {
566 pr_warning("bpf relocation: map_idx %d large than %d\n",
567 (int)map_idx, (int)nr_maps - 1);
568 return -EINVAL;
569 }
570
571 prog->reloc_desc[i].insn_idx = insn_idx;
572 prog->reloc_desc[i].map_idx = map_idx;
573 }
574 return 0;
575}
576
52d3352e
WN
577static int
578bpf_object__create_maps(struct bpf_object *obj)
579{
580 unsigned int i;
581 size_t nr_maps;
582 int *pfd;
583
584 nr_maps = obj->maps_buf_sz / sizeof(struct bpf_map_def);
585 if (!obj->maps_buf || !nr_maps) {
586 pr_debug("don't need create maps for %s\n",
587 obj->path);
588 return 0;
589 }
590
591 obj->map_fds = malloc(sizeof(int) * nr_maps);
592 if (!obj->map_fds) {
593 pr_warning("realloc perf_bpf_map_fds failed\n");
594 return -ENOMEM;
595 }
596 obj->nr_map_fds = nr_maps;
597
598 /* fill all fd with -1 */
599 memset(obj->map_fds, -1, sizeof(int) * nr_maps);
600
601 pfd = obj->map_fds;
602 for (i = 0; i < nr_maps; i++) {
603 struct bpf_map_def def;
604
605 def = *(struct bpf_map_def *)(obj->maps_buf +
606 i * sizeof(struct bpf_map_def));
607
608 *pfd = bpf_create_map(def.type,
609 def.key_size,
610 def.value_size,
611 def.max_entries);
612 if (*pfd < 0) {
613 size_t j;
614 int err = *pfd;
615
616 pr_warning("failed to create map: %s\n",
617 strerror(errno));
618 for (j = 0; j < i; j++)
619 zclose(obj->map_fds[j]);
620 obj->nr_map_fds = 0;
621 zfree(&obj->map_fds);
622 return err;
623 }
624 pr_debug("create map: fd=%d\n", *pfd);
625 pfd++;
626 }
627
628 zfree(&obj->maps_buf);
629 obj->maps_buf_sz = 0;
630 return 0;
631}
632
8a47a6c5
WN
633static int
634bpf_program__relocate(struct bpf_program *prog, int *map_fds)
635{
636 int i;
637
638 if (!prog || !prog->reloc_desc)
639 return 0;
640
641 for (i = 0; i < prog->nr_reloc; i++) {
642 int insn_idx, map_idx;
643 struct bpf_insn *insns = prog->insns;
644
645 insn_idx = prog->reloc_desc[i].insn_idx;
646 map_idx = prog->reloc_desc[i].map_idx;
647
648 if (insn_idx >= (int)prog->insns_cnt) {
649 pr_warning("relocation out of range: '%s'\n",
650 prog->section_name);
651 return -ERANGE;
652 }
653 insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
654 insns[insn_idx].imm = map_fds[map_idx];
655 }
656
657 zfree(&prog->reloc_desc);
658 prog->nr_reloc = 0;
659 return 0;
660}
661
662
663static int
664bpf_object__relocate(struct bpf_object *obj)
665{
666 struct bpf_program *prog;
667 size_t i;
668 int err;
669
670 for (i = 0; i < obj->nr_programs; i++) {
671 prog = &obj->programs[i];
672
673 err = bpf_program__relocate(prog, obj->map_fds);
674 if (err) {
675 pr_warning("failed to relocate '%s'\n",
676 prog->section_name);
677 return err;
678 }
679 }
680 return 0;
681}
682
34090915
WN
683static int bpf_object__collect_reloc(struct bpf_object *obj)
684{
685 int i, err;
686
687 if (!obj_elf_valid(obj)) {
688 pr_warning("Internal error: elf object is closed\n");
689 return -EINVAL;
690 }
691
692 for (i = 0; i < obj->efile.nr_reloc; i++) {
693 GElf_Shdr *shdr = &obj->efile.reloc[i].shdr;
694 Elf_Data *data = obj->efile.reloc[i].data;
695 int idx = shdr->sh_info;
696 struct bpf_program *prog;
697 size_t nr_maps = obj->maps_buf_sz /
698 sizeof(struct bpf_map_def);
699
700 if (shdr->sh_type != SHT_REL) {
701 pr_warning("internal error at %d\n", __LINE__);
702 return -EINVAL;
703 }
704
705 prog = bpf_object__find_prog_by_idx(obj, idx);
706 if (!prog) {
707 pr_warning("relocation failed: no %d section\n",
708 idx);
709 return -ENOENT;
710 }
711
712 err = bpf_program__collect_reloc(prog, nr_maps,
713 shdr, data,
714 obj->efile.symbols);
715 if (err)
716 return -EINVAL;
717 }
718 return 0;
719}
720
cb1e5e96
WN
721static int bpf_object__validate(struct bpf_object *obj)
722{
723 if (obj->kern_version == 0) {
724 pr_warning("%s doesn't provide kernel version\n",
725 obj->path);
726 return -EINVAL;
727 }
728 return 0;
729}
730
1a5e3fb1 731static struct bpf_object *
6c956392 732__bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz)
1a5e3fb1
WN
733{
734 struct bpf_object *obj;
735
736 if (elf_version(EV_CURRENT) == EV_NONE) {
737 pr_warning("failed to init libelf for %s\n", path);
738 return NULL;
739 }
740
6c956392 741 obj = bpf_object__new(path, obj_buf, obj_buf_sz);
1a5e3fb1
WN
742 if (!obj)
743 return NULL;
744
745 if (bpf_object__elf_init(obj))
746 goto out;
cc4228d5
WN
747 if (bpf_object__check_endianness(obj))
748 goto out;
29603665
WN
749 if (bpf_object__elf_collect(obj))
750 goto out;
34090915
WN
751 if (bpf_object__collect_reloc(obj))
752 goto out;
cb1e5e96
WN
753 if (bpf_object__validate(obj))
754 goto out;
1a5e3fb1
WN
755
756 bpf_object__elf_finish(obj);
757 return obj;
758out:
759 bpf_object__close(obj);
760 return NULL;
761}
762
763struct bpf_object *bpf_object__open(const char *path)
764{
765 /* param validation */
766 if (!path)
767 return NULL;
768
769 pr_debug("loading %s\n", path);
770
6c956392
WN
771 return __bpf_object__open(path, NULL, 0);
772}
773
774struct bpf_object *bpf_object__open_buffer(void *obj_buf,
775 size_t obj_buf_sz)
776{
777 /* param validation */
778 if (!obj_buf || obj_buf_sz <= 0)
779 return NULL;
780
781 pr_debug("loading object from buffer\n");
782
783 return __bpf_object__open("[buffer]", obj_buf, obj_buf_sz);
1a5e3fb1
WN
784}
785
52d3352e
WN
786int bpf_object__unload(struct bpf_object *obj)
787{
788 size_t i;
789
790 if (!obj)
791 return -EINVAL;
792
793 for (i = 0; i < obj->nr_map_fds; i++)
794 zclose(obj->map_fds[i]);
795 zfree(&obj->map_fds);
796 obj->nr_map_fds = 0;
797
798 return 0;
799}
800
801int bpf_object__load(struct bpf_object *obj)
802{
803 if (!obj)
804 return -EINVAL;
805
806 if (obj->loaded) {
807 pr_warning("object should not be loaded twice\n");
808 return -EINVAL;
809 }
810
811 obj->loaded = true;
812 if (bpf_object__create_maps(obj))
813 goto out;
8a47a6c5
WN
814 if (bpf_object__relocate(obj))
815 goto out;
52d3352e
WN
816
817 return 0;
818out:
819 bpf_object__unload(obj);
820 pr_warning("failed to load object '%s'\n", obj->path);
821 return -EINVAL;
822}
823
1a5e3fb1
WN
824void bpf_object__close(struct bpf_object *obj)
825{
a5b8bd47
WN
826 size_t i;
827
1a5e3fb1
WN
828 if (!obj)
829 return;
830
831 bpf_object__elf_finish(obj);
52d3352e 832 bpf_object__unload(obj);
1a5e3fb1 833
0b3d1efa 834 zfree(&obj->maps_buf);
a5b8bd47
WN
835
836 if (obj->programs && obj->nr_programs) {
837 for (i = 0; i < obj->nr_programs; i++)
838 bpf_program__exit(&obj->programs[i]);
839 }
840 zfree(&obj->programs);
841
1a5e3fb1
WN
842 free(obj);
843}
This page took 0.059757 seconds and 5 git commands to generate.