Skip to content

Commit b4ff7ad

Browse files
author
Alexei Starovoitov
committed
Merge branch 'libbpf-support-bpf-to-bpf-calls'
Andrii Nakryiko says: ==================== Currently, libbpf supports a limited form of BPF-to-BPF subprogram calls. The restriction is that entry-point BPF program should use *all* of defined sub-programs in BPF .o file. If any of the subprograms is not used, such entry-point BPF program will be rejected by verifier as containing unreachable dead code. This is not a big limitation for cases with single entry-point BPF programs, but is quite a heavy restriction for multi-programs that use only partially overlapping set of subprograms. This patch set removes all such restrictions and adds complete support for using BPF sub-program calls on BPF side. This is achieved through libbpf tracking subprograms individually and detecting which subprograms are used by any given entry-point BPF program, and subsequently only appending and relocating code for just those used subprograms. In addition, libbpf now also supports multiple entry-point BPF programs within the same ELF section. This allows to structure code so that there are few variants of BPF programs of the same type and attaching to the same target (e.g., for tracepoints and kprobes) without the need to worry about ELF section name clashes. This patch set opens way for more wider adoption of BPF subprogram calls, especially for real-world production use-cases with complicated net of subprograms. This will allow to further scale BPF verification process through good use of global functions, which can be verified independently. This is also important prerequisite for static linking which allows static BPF libraries to not worry about naming clashes for section names, as well as use static non-inlined functions (subprograms) without worries of verifier rejecting program due to dead code. Patch set is structured as follows: - patched 1-6 contain all the libbpf changes necessary to support multi-prog sections and bpf2bpf subcalls; - patch 7 adds dedicated selftests validating all combinations of possible sub-calls (within and across sections, static vs global functions); - patch 8 deprecated bpf_program__title() in favor of bpf_program__section_name(). The intent was to also deprecate bpf_object__find_program_by_title() as it's now non-sensical with multiple programs per section. But there were too many selftests uses of this and I didn't want to delay this patches further and make it even bigger, so left it for a follow up cleanup; - patches 9-10 remove uses for title-related APIs from bpftool and bpf_program__title() use from selftests; - patch 11 is converting fexit_bpf2bpf to have explicit subtest (it does contain 4 subtests, which are not handled as sub-tests); - patches 12-14 convert few complicated BPF selftests to use __noinline functions to further validate correctness of libbpf's bpf2bpf processing logic. v2->v3: - explained subprog relocation algorithm in more details (Alexei); - pyperf, strobelight and cls_redirect got new subprog variants, leaving other modes intact (Alexei); v1->v2: - rename DEPRECATED to LIBBPF_DEPRECATED to avoid name clashes; - fix test_subprogs build; - convert a bunch of complicated selftests to __noinline (Alexei). ==================== Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents 83cf5c6 + ee333df commit b4ff7ad

24 files changed

+1247
-611
lines changed

tools/bpf/bpftool/prog.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,7 +1304,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
13041304
enum bpf_prog_type prog_type = common_prog_type;
13051305

13061306
if (prog_type == BPF_PROG_TYPE_UNSPEC) {
1307-
const char *sec_name = bpf_program__title(pos, false);
1307+
const char *sec_name = bpf_program__section_name(pos);
13081308

13091309
err = get_prog_type_by_name(sec_name, &prog_type,
13101310
&expected_attach_type);
@@ -1398,7 +1398,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
13981398
err = bpf_obj_pin(bpf_program__fd(prog), pinfile);
13991399
if (err) {
14001400
p_err("failed to pin program %s",
1401-
bpf_program__title(prog, false));
1401+
bpf_program__section_name(prog));
14021402
goto err_close_obj;
14031403
}
14041404
} else {

tools/lib/bpf/btf.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,16 @@ LIBBPF_API struct btf_ext *btf_ext__new(__u8 *data, __u32 size);
5757
LIBBPF_API void btf_ext__free(struct btf_ext *btf_ext);
5858
LIBBPF_API const void *btf_ext__get_raw_data(const struct btf_ext *btf_ext,
5959
__u32 *size);
60-
LIBBPF_API int btf_ext__reloc_func_info(const struct btf *btf,
61-
const struct btf_ext *btf_ext,
62-
const char *sec_name, __u32 insns_cnt,
63-
void **func_info, __u32 *cnt);
64-
LIBBPF_API int btf_ext__reloc_line_info(const struct btf *btf,
65-
const struct btf_ext *btf_ext,
66-
const char *sec_name, __u32 insns_cnt,
67-
void **line_info, __u32 *cnt);
60+
LIBBPF_API LIBBPF_DEPRECATED("btf_ext__reloc_func_info was never meant as a public API and has wrong assumptions embedded in it; it will be removed in the future libbpf versions")
61+
int btf_ext__reloc_func_info(const struct btf *btf,
62+
const struct btf_ext *btf_ext,
63+
const char *sec_name, __u32 insns_cnt,
64+
void **func_info, __u32 *cnt);
65+
LIBBPF_API LIBBPF_DEPRECATED("btf_ext__reloc_line_info was never meant as a public API and has wrong assumptions embedded in it; it will be removed in the future libbpf versions")
66+
int btf_ext__reloc_line_info(const struct btf *btf,
67+
const struct btf_ext *btf_ext,
68+
const char *sec_name, __u32 insns_cnt,
69+
void **line_info, __u32 *cnt);
6870
LIBBPF_API __u32 btf_ext__func_info_rec_size(const struct btf_ext *btf_ext);
6971
LIBBPF_API __u32 btf_ext__line_info_rec_size(const struct btf_ext *btf_ext);
7072

0 commit comments

Comments
 (0)