bpf tools: Collect relocation sections from SHT_REL sections
[linux-2.6-block.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>
12#include <string.h>
1b76c13e 13#include <unistd.h>
1a5e3fb1
WN
14#include <fcntl.h>
15#include <errno.h>
1b76c13e 16#include <asm/unistd.h>
cb1e5e96 17#include <linux/kernel.h>
1b76c13e 18#include <linux/bpf.h>
1a5e3fb1
WN
19#include <libelf.h>
20#include <gelf.h>
1b76c13e
WN
21
22#include "libbpf.h"
b3f59d66
WN
23
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}
1a5e3fb1
WN
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
a5b8bd47
WN
81/*
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
1a5e3fb1 93struct bpf_object {
cb1e5e96
WN
94 char license[64];
95 u32 kern_version;
0b3d1efa
WN
96 void *maps_buf;
97 size_t maps_buf_sz;
98
a5b8bd47
WN
99 struct bpf_program *programs;
100 size_t nr_programs;
101
1a5e3fb1
WN
102 /*
103 * Information when doing elf related work. Only valid if fd
104 * is valid.
105 */
106 struct {
107 int fd;
6c956392
WN
108 void *obj_buf;
109 size_t obj_buf_sz;
1a5e3fb1
WN
110 Elf *elf;
111 GElf_Ehdr ehdr;
bec7d68c 112 Elf_Data *symbols;
b62f06e8
WN
113 struct {
114 GElf_Shdr shdr;
115 Elf_Data *data;
116 } *reloc;
117 int nr_reloc;
1a5e3fb1
WN
118 } efile;
119 char path[];
120};
121#define obj_elf_valid(o) ((o)->efile.elf)
122
a5b8bd47
WN
123static void bpf_program__exit(struct bpf_program *prog)
124{
125 if (!prog)
126 return;
127
128 zfree(&prog->section_name);
129 zfree(&prog->insns);
130 prog->insns_cnt = 0;
131 prog->idx = -1;
132}
133
134static int
135bpf_program__init(void *data, size_t size, char *name, int idx,
136 struct bpf_program *prog)
137{
138 if (size < sizeof(struct bpf_insn)) {
139 pr_warning("corrupted section '%s'\n", name);
140 return -EINVAL;
141 }
142
143 bzero(prog, sizeof(*prog));
144
145 prog->section_name = strdup(name);
146 if (!prog->section_name) {
147 pr_warning("failed to alloc name for prog %s\n",
148 name);
149 goto errout;
150 }
151
152 prog->insns = malloc(size);
153 if (!prog->insns) {
154 pr_warning("failed to alloc insns for %s\n", name);
155 goto errout;
156 }
157 prog->insns_cnt = size / sizeof(struct bpf_insn);
158 memcpy(prog->insns, data,
159 prog->insns_cnt * sizeof(struct bpf_insn));
160 prog->idx = idx;
161
162 return 0;
163errout:
164 bpf_program__exit(prog);
165 return -ENOMEM;
166}
167
168static int
169bpf_object__add_program(struct bpf_object *obj, void *data, size_t size,
170 char *name, int idx)
171{
172 struct bpf_program prog, *progs;
173 int nr_progs, err;
174
175 err = bpf_program__init(data, size, name, idx, &prog);
176 if (err)
177 return err;
178
179 progs = obj->programs;
180 nr_progs = obj->nr_programs;
181
182 progs = realloc(progs, sizeof(progs[0]) * (nr_progs + 1));
183 if (!progs) {
184 /*
185 * In this case the original obj->programs
186 * is still valid, so don't need special treat for
187 * bpf_close_object().
188 */
189 pr_warning("failed to alloc a new program '%s'\n",
190 name);
191 bpf_program__exit(&prog);
192 return -ENOMEM;
193 }
194
195 pr_debug("found program %s\n", prog.section_name);
196 obj->programs = progs;
197 obj->nr_programs = nr_progs + 1;
198 progs[nr_progs] = prog;
199 return 0;
200}
201
6c956392
WN
202static struct bpf_object *bpf_object__new(const char *path,
203 void *obj_buf,
204 size_t obj_buf_sz)
1a5e3fb1
WN
205{
206 struct bpf_object *obj;
207
208 obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1);
209 if (!obj) {
210 pr_warning("alloc memory failed for %s\n", path);
211 return NULL;
212 }
213
214 strcpy(obj->path, path);
215 obj->efile.fd = -1;
6c956392
WN
216
217 /*
218 * Caller of this function should also calls
219 * bpf_object__elf_finish() after data collection to return
220 * obj_buf to user. If not, we should duplicate the buffer to
221 * avoid user freeing them before elf finish.
222 */
223 obj->efile.obj_buf = obj_buf;
224 obj->efile.obj_buf_sz = obj_buf_sz;
225
1a5e3fb1
WN
226 return obj;
227}
228
229static void bpf_object__elf_finish(struct bpf_object *obj)
230{
231 if (!obj_elf_valid(obj))
232 return;
233
234 if (obj->efile.elf) {
235 elf_end(obj->efile.elf);
236 obj->efile.elf = NULL;
237 }
bec7d68c 238 obj->efile.symbols = NULL;
b62f06e8
WN
239
240 zfree(&obj->efile.reloc);
241 obj->efile.nr_reloc = 0;
1a5e3fb1 242 zclose(obj->efile.fd);
6c956392
WN
243 obj->efile.obj_buf = NULL;
244 obj->efile.obj_buf_sz = 0;
1a5e3fb1
WN
245}
246
247static int bpf_object__elf_init(struct bpf_object *obj)
248{
249 int err = 0;
250 GElf_Ehdr *ep;
251
252 if (obj_elf_valid(obj)) {
253 pr_warning("elf init: internal error\n");
254 return -EEXIST;
255 }
256
6c956392
WN
257 if (obj->efile.obj_buf_sz > 0) {
258 /*
259 * obj_buf should have been validated by
260 * bpf_object__open_buffer().
261 */
262 obj->efile.elf = elf_memory(obj->efile.obj_buf,
263 obj->efile.obj_buf_sz);
264 } else {
265 obj->efile.fd = open(obj->path, O_RDONLY);
266 if (obj->efile.fd < 0) {
267 pr_warning("failed to open %s: %s\n", obj->path,
268 strerror(errno));
269 return -errno;
270 }
271
272 obj->efile.elf = elf_begin(obj->efile.fd,
273 LIBBPF_ELF_C_READ_MMAP,
274 NULL);
1a5e3fb1
WN
275 }
276
1a5e3fb1
WN
277 if (!obj->efile.elf) {
278 pr_warning("failed to open %s as ELF file\n",
279 obj->path);
280 err = -EINVAL;
281 goto errout;
282 }
283
284 if (!gelf_getehdr(obj->efile.elf, &obj->efile.ehdr)) {
285 pr_warning("failed to get EHDR from %s\n",
286 obj->path);
287 err = -EINVAL;
288 goto errout;
289 }
290 ep = &obj->efile.ehdr;
291
292 if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) {
293 pr_warning("%s is not an eBPF object file\n",
294 obj->path);
295 err = -EINVAL;
296 goto errout;
297 }
298
299 return 0;
300errout:
301 bpf_object__elf_finish(obj);
302 return err;
303}
304
cc4228d5
WN
305static int
306bpf_object__check_endianness(struct bpf_object *obj)
307{
308 static unsigned int const endian = 1;
309
310 switch (obj->efile.ehdr.e_ident[EI_DATA]) {
311 case ELFDATA2LSB:
312 /* We are big endian, BPF obj is little endian. */
313 if (*(unsigned char const *)&endian != 1)
314 goto mismatch;
315 break;
316
317 case ELFDATA2MSB:
318 /* We are little endian, BPF obj is big endian. */
319 if (*(unsigned char const *)&endian != 0)
320 goto mismatch;
321 break;
322 default:
323 return -EINVAL;
324 }
325
326 return 0;
327
328mismatch:
329 pr_warning("Error: endianness mismatch.\n");
330 return -EINVAL;
331}
332
cb1e5e96
WN
333static int
334bpf_object__init_license(struct bpf_object *obj,
335 void *data, size_t size)
336{
337 memcpy(obj->license, data,
338 min(size, sizeof(obj->license) - 1));
339 pr_debug("license of %s is %s\n", obj->path, obj->license);
340 return 0;
341}
342
343static int
344bpf_object__init_kversion(struct bpf_object *obj,
345 void *data, size_t size)
346{
347 u32 kver;
348
349 if (size != sizeof(kver)) {
350 pr_warning("invalid kver section in %s\n", obj->path);
351 return -EINVAL;
352 }
353 memcpy(&kver, data, sizeof(kver));
354 obj->kern_version = kver;
355 pr_debug("kernel version of %s is %x\n", obj->path,
356 obj->kern_version);
357 return 0;
358}
359
0b3d1efa
WN
360static int
361bpf_object__init_maps(struct bpf_object *obj, void *data,
362 size_t size)
363{
364 if (size == 0) {
365 pr_debug("%s doesn't need map definition\n",
366 obj->path);
367 return 0;
368 }
369
370 obj->maps_buf = malloc(size);
371 if (!obj->maps_buf) {
372 pr_warning("malloc maps failed: %s\n", obj->path);
373 return -ENOMEM;
374 }
375
376 obj->maps_buf_sz = size;
377 memcpy(obj->maps_buf, data, size);
378 pr_debug("maps in %s: %ld bytes\n", obj->path, (long)size);
379 return 0;
380}
381
29603665
WN
382static int bpf_object__elf_collect(struct bpf_object *obj)
383{
384 Elf *elf = obj->efile.elf;
385 GElf_Ehdr *ep = &obj->efile.ehdr;
386 Elf_Scn *scn = NULL;
387 int idx = 0, err = 0;
388
389 /* Elf is corrupted/truncated, avoid calling elf_strptr. */
390 if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
391 pr_warning("failed to get e_shstrndx from %s\n",
392 obj->path);
393 return -EINVAL;
394 }
395
396 while ((scn = elf_nextscn(elf, scn)) != NULL) {
397 char *name;
398 GElf_Shdr sh;
399 Elf_Data *data;
400
401 idx++;
402 if (gelf_getshdr(scn, &sh) != &sh) {
403 pr_warning("failed to get section header from %s\n",
404 obj->path);
405 err = -EINVAL;
406 goto out;
407 }
408
409 name = elf_strptr(elf, ep->e_shstrndx, sh.sh_name);
410 if (!name) {
411 pr_warning("failed to get section name from %s\n",
412 obj->path);
413 err = -EINVAL;
414 goto out;
415 }
416
417 data = elf_getdata(scn, 0);
418 if (!data) {
419 pr_warning("failed to get section data from %s(%s)\n",
420 name, obj->path);
421 err = -EINVAL;
422 goto out;
423 }
424 pr_debug("section %s, size %ld, link %d, flags %lx, type=%d\n",
425 name, (unsigned long)data->d_size,
426 (int)sh.sh_link, (unsigned long)sh.sh_flags,
427 (int)sh.sh_type);
cb1e5e96
WN
428
429 if (strcmp(name, "license") == 0)
430 err = bpf_object__init_license(obj,
431 data->d_buf,
432 data->d_size);
433 else if (strcmp(name, "version") == 0)
434 err = bpf_object__init_kversion(obj,
435 data->d_buf,
436 data->d_size);
0b3d1efa
WN
437 else if (strcmp(name, "maps") == 0)
438 err = bpf_object__init_maps(obj, data->d_buf,
439 data->d_size);
bec7d68c
WN
440 else if (sh.sh_type == SHT_SYMTAB) {
441 if (obj->efile.symbols) {
442 pr_warning("bpf: multiple SYMTAB in %s\n",
443 obj->path);
444 err = -EEXIST;
445 } else
446 obj->efile.symbols = data;
a5b8bd47
WN
447 } else if ((sh.sh_type == SHT_PROGBITS) &&
448 (sh.sh_flags & SHF_EXECINSTR) &&
449 (data->d_size > 0)) {
450 err = bpf_object__add_program(obj, data->d_buf,
451 data->d_size, name, idx);
452 if (err) {
453 char errmsg[128];
454 strerror_r(-err, errmsg, sizeof(errmsg));
455 pr_warning("failed to alloc program %s (%s): %s",
456 name, obj->path, errmsg);
457 }
b62f06e8
WN
458 } else if (sh.sh_type == SHT_REL) {
459 void *reloc = obj->efile.reloc;
460 int nr_reloc = obj->efile.nr_reloc + 1;
461
462 reloc = realloc(reloc,
463 sizeof(*obj->efile.reloc) * nr_reloc);
464 if (!reloc) {
465 pr_warning("realloc failed\n");
466 err = -ENOMEM;
467 } else {
468 int n = nr_reloc - 1;
469
470 obj->efile.reloc = reloc;
471 obj->efile.nr_reloc = nr_reloc;
472
473 obj->efile.reloc[n].shdr = sh;
474 obj->efile.reloc[n].data = data;
475 }
bec7d68c 476 }
cb1e5e96
WN
477 if (err)
478 goto out;
29603665
WN
479 }
480out:
481 return err;
482}
483
cb1e5e96
WN
484static int bpf_object__validate(struct bpf_object *obj)
485{
486 if (obj->kern_version == 0) {
487 pr_warning("%s doesn't provide kernel version\n",
488 obj->path);
489 return -EINVAL;
490 }
491 return 0;
492}
493
1a5e3fb1 494static struct bpf_object *
6c956392 495__bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz)
1a5e3fb1
WN
496{
497 struct bpf_object *obj;
498
499 if (elf_version(EV_CURRENT) == EV_NONE) {
500 pr_warning("failed to init libelf for %s\n", path);
501 return NULL;
502 }
503
6c956392 504 obj = bpf_object__new(path, obj_buf, obj_buf_sz);
1a5e3fb1
WN
505 if (!obj)
506 return NULL;
507
508 if (bpf_object__elf_init(obj))
509 goto out;
cc4228d5
WN
510 if (bpf_object__check_endianness(obj))
511 goto out;
29603665
WN
512 if (bpf_object__elf_collect(obj))
513 goto out;
cb1e5e96
WN
514 if (bpf_object__validate(obj))
515 goto out;
1a5e3fb1
WN
516
517 bpf_object__elf_finish(obj);
518 return obj;
519out:
520 bpf_object__close(obj);
521 return NULL;
522}
523
524struct bpf_object *bpf_object__open(const char *path)
525{
526 /* param validation */
527 if (!path)
528 return NULL;
529
530 pr_debug("loading %s\n", path);
531
6c956392
WN
532 return __bpf_object__open(path, NULL, 0);
533}
534
535struct bpf_object *bpf_object__open_buffer(void *obj_buf,
536 size_t obj_buf_sz)
537{
538 /* param validation */
539 if (!obj_buf || obj_buf_sz <= 0)
540 return NULL;
541
542 pr_debug("loading object from buffer\n");
543
544 return __bpf_object__open("[buffer]", obj_buf, obj_buf_sz);
1a5e3fb1
WN
545}
546
547void bpf_object__close(struct bpf_object *obj)
548{
a5b8bd47
WN
549 size_t i;
550
1a5e3fb1
WN
551 if (!obj)
552 return;
553
554 bpf_object__elf_finish(obj);
555
0b3d1efa 556 zfree(&obj->maps_buf);
a5b8bd47
WN
557
558 if (obj->programs && obj->nr_programs) {
559 for (i = 0; i < obj->nr_programs; i++)
560 bpf_program__exit(&obj->programs[i]);
561 }
562 zfree(&obj->programs);
563
1a5e3fb1
WN
564 free(obj);
565}