Skip to content

Commit faf6ed3

Browse files
anakryikoAlexei Starovoitov
authored andcommitted
libbpf: Add BPF static linker APIs
Introduce BPF static linker APIs to libbpf. BPF static linker allows to perform static linking of multiple BPF object files into a single combined resulting object file, preserving all the BPF programs, maps, global variables, etc. Data sections (.bss, .data, .rodata, .maps, maps, etc) with the same name are concatenated together. Similarly, code sections are also concatenated. All the symbols and ELF relocations are also concatenated in their respective ELF sections and are adjusted accordingly to the new object file layout. Static variables and functions are handled correctly as well, adjusting BPF instructions offsets to reflect new variable/function offset within the combined ELF section. Such relocations are referencing STT_SECTION symbols and that stays intact. Data sections in different files can have different alignment requirements, so that is taken care of as well, adjusting sizes and offsets as necessary to satisfy both old and new alignment requirements. DWARF data sections are stripped out, currently. As well as LLLVM_ADDRSIG section, which is ignored by libbpf in bpf_object__open() anyways. So, in a way, BPF static linker is an analogue to `llvm-strip -g`, which is a pretty nice property, especially if resulting .o file is then used to generate BPF skeleton. Original string sections are ignored and instead we construct our own set of unique strings using libbpf-internal `struct strset` API. To reduce the size of the patch, all the .BTF and .BTF.ext processing was moved into a separate patch. The high-level API consists of just 4 functions: - bpf_linker__new() creates an instance of BPF static linker. It accepts output filename and (currently empty) options struct; - bpf_linker__add_file() takes input filename and appends it to the already processed ELF data; it can be called multiple times, one for each BPF ELF object file that needs to be linked in; - bpf_linker__finalize() needs to be called to dump final ELF contents into the output file, specified when bpf_linker was created; after bpf_linker__finalize() is called, no more bpf_linker__add_file() and bpf_linker__finalize() calls are allowed, they will return error; - regardless of whether bpf_linker__finalize() was called or not, bpf_linker__free() will free up all the used resources. Currently, BPF static linker doesn't resolve cross-object file references (extern variables and/or functions). This will be added in the follow up patch set. Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20210318194036.3521577-7-andrii@kernel.org
1 parent 9af44bc commit faf6ed3

File tree

6 files changed

+1215
-11
lines changed

6 files changed

+1215
-11
lines changed

tools/lib/bpf/Build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_errno.o str_error.o \
22
netlink.o bpf_prog_linfo.o libbpf_probes.o xsk.o hashmap.o \
3-
btf_dump.o ringbuf.o strset.o
3+
btf_dump.o ringbuf.o strset.o linker.o

tools/lib/bpf/libbpf.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,6 @@
5555
#include "libbpf_internal.h"
5656
#include "hashmap.h"
5757

58-
#ifndef EM_BPF
59-
#define EM_BPF 247
60-
#endif
61-
6258
#ifndef BPF_FS_MAGIC
6359
#define BPF_FS_MAGIC 0xcafe4a11
6460
#endif
@@ -1134,11 +1130,6 @@ static void bpf_object__elf_finish(struct bpf_object *obj)
11341130
obj->efile.obj_buf_sz = 0;
11351131
}
11361132

1137-
/* if libelf is old and doesn't support mmap(), fall back to read() */
1138-
#ifndef ELF_C_READ_MMAP
1139-
#define ELF_C_READ_MMAP ELF_C_READ
1140-
#endif
1141-
11421133
static int bpf_object__elf_init(struct bpf_object *obj)
11431134
{
11441135
int err = 0;
@@ -2807,7 +2798,7 @@ static bool ignore_elf_section(GElf_Shdr *hdr, const char *name)
28072798
return true;
28082799

28092800
/* ignore .llvm_addrsig section as well */
2810-
if (hdr->sh_type == 0x6FFF4C03 /* SHT_LLVM_ADDRSIG */)
2801+
if (hdr->sh_type == SHT_LLVM_ADDRSIG)
28112802
return true;
28122803

28132804
/* no subprograms will lead to an empty .text section, ignore it */

tools/lib/bpf/libbpf.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,19 @@ enum libbpf_tristate {
760760
TRI_MODULE = 2,
761761
};
762762

763+
struct bpf_linker_opts {
764+
/* size of this struct, for forward/backward compatiblity */
765+
size_t sz;
766+
};
767+
#define bpf_linker_opts__last_field sz
768+
769+
struct bpf_linker;
770+
771+
LIBBPF_API struct bpf_linker *bpf_linker__new(const char *filename, struct bpf_linker_opts *opts);
772+
LIBBPF_API int bpf_linker__add_file(struct bpf_linker *linker, const char *filename);
773+
LIBBPF_API int bpf_linker__finalize(struct bpf_linker *linker);
774+
LIBBPF_API void bpf_linker__free(struct bpf_linker *linker);
775+
763776
#ifdef __cplusplus
764777
} /* extern "C" */
765778
#endif

tools/lib/bpf/libbpf.map

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,4 +355,8 @@ LIBBPF_0.4.0 {
355355
global:
356356
btf__add_float;
357357
btf__add_type;
358+
bpf_linker__add_file;
359+
bpf_linker__finalize;
360+
bpf_linker__free;
361+
bpf_linker__new;
358362
} LIBBPF_0.3.0;

tools/lib/bpf/libbpf_internal.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,26 @@
2020

2121
#include "libbpf.h"
2222

23+
#ifndef EM_BPF
24+
#define EM_BPF 247
25+
#endif
26+
27+
#ifndef R_BPF_64_64
28+
#define R_BPF_64_64 1
29+
#endif
30+
#ifndef R_BPF_64_32
31+
#define R_BPF_64_32 10
32+
#endif
33+
34+
#ifndef SHT_LLVM_ADDRSIG
35+
#define SHT_LLVM_ADDRSIG 0x6FFF4C03
36+
#endif
37+
38+
/* if libelf is old and doesn't support mmap(), fall back to read() */
39+
#ifndef ELF_C_READ_MMAP
40+
#define ELF_C_READ_MMAP ELF_C_READ
41+
#endif
42+
2343
#define BTF_INFO_ENC(kind, kind_flag, vlen) \
2444
((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
2545
#define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type)

0 commit comments

Comments
 (0)