• Andrii Nakryiko's avatar
    libbpf: Add BPF static linker APIs · faf6ed32
    Andrii Nakryiko authored
    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: default avatarAndrii Nakryiko <andrii@kernel.org>
    Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    Link: https://lore.kernel.org/bpf/20210318194036.3521577-7-andrii@kernel.org
    faf6ed32
linker.c 29 KB