Skip to content

Commit f75a697

Browse files
Alexei Starovoitovborkmann
authored andcommitted
libbpf: Auto-detect btf_id of BTF-based raw_tracepoints
It's a responsiblity of bpf program author to annotate the program with SEC("tp_btf/name") where "name" is a valid raw tracepoint. The libbpf will try to find "name" in vmlinux BTF and error out in case vmlinux BTF is not available or "name" is not found. If "name" is indeed a valid raw tracepoint then in-kernel BTF will have "btf_trace_##name" typedef that points to function prototype of that raw tracepoint. BTF description captures exact argument the kernel C code is passing into raw tracepoint. The kernel verifier will check the types while loading bpf program. libbpf keeps BTF type id in expected_attach_type, but since kernel ignores this attribute for tracing programs copy it into attach_btf_id attribute before loading. Later the kernel will use prog->attach_btf_id to select raw tracepoint during bpf_raw_tracepoint_open syscall command. Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Acked-by: Martin KaFai Lau <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent ccfe29e commit f75a697

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

tools/lib/bpf/bpf.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
228228
memset(&attr, 0, sizeof(attr));
229229
attr.prog_type = load_attr->prog_type;
230230
attr.expected_attach_type = load_attr->expected_attach_type;
231+
if (attr.prog_type == BPF_PROG_TYPE_RAW_TRACEPOINT)
232+
/* expected_attach_type is ignored for tracing progs */
233+
attr.attach_btf_id = attr.expected_attach_type;
231234
attr.insn_cnt = (__u32)load_attr->insns_cnt;
232235
attr.insns = ptr_to_u64(load_attr->insns);
233236
attr.license = ptr_to_u64(load_attr->license);

tools/lib/bpf/libbpf.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4489,19 +4489,22 @@ void bpf_program__set_expected_attach_type(struct bpf_program *prog,
44894489
prog->expected_attach_type = type;
44904490
}
44914491

4492-
#define BPF_PROG_SEC_IMPL(string, ptype, eatype, is_attachable, atype) \
4493-
{ string, sizeof(string) - 1, ptype, eatype, is_attachable, atype }
4492+
#define BPF_PROG_SEC_IMPL(string, ptype, eatype, is_attachable, btf, atype) \
4493+
{ string, sizeof(string) - 1, ptype, eatype, is_attachable, btf, atype }
44944494

44954495
/* Programs that can NOT be attached. */
4496-
#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, 0, 0)
4496+
#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, 0, 0, 0)
44974497

44984498
/* Programs that can be attached. */
44994499
#define BPF_APROG_SEC(string, ptype, atype) \
4500-
BPF_PROG_SEC_IMPL(string, ptype, 0, 1, atype)
4500+
BPF_PROG_SEC_IMPL(string, ptype, 0, 1, 0, atype)
45014501

45024502
/* Programs that must specify expected attach type at load time. */
45034503
#define BPF_EAPROG_SEC(string, ptype, eatype) \
4504-
BPF_PROG_SEC_IMPL(string, ptype, eatype, 1, eatype)
4504+
BPF_PROG_SEC_IMPL(string, ptype, eatype, 1, 0, eatype)
4505+
4506+
/* Programs that use BTF to identify attach point */
4507+
#define BPF_PROG_BTF(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, 0, 1, 0)
45054508

45064509
/* Programs that can be attached but attach type can't be identified by section
45074510
* name. Kept for backward compatibility.
@@ -4513,7 +4516,8 @@ static const struct {
45134516
size_t len;
45144517
enum bpf_prog_type prog_type;
45154518
enum bpf_attach_type expected_attach_type;
4516-
int is_attachable;
4519+
bool is_attachable;
4520+
bool is_attach_btf;
45174521
enum bpf_attach_type attach_type;
45184522
} section_names[] = {
45194523
BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER),
@@ -4523,6 +4527,7 @@ static const struct {
45234527
BPF_PROG_SEC("action", BPF_PROG_TYPE_SCHED_ACT),
45244528
BPF_PROG_SEC("tracepoint/", BPF_PROG_TYPE_TRACEPOINT),
45254529
BPF_PROG_SEC("raw_tracepoint/", BPF_PROG_TYPE_RAW_TRACEPOINT),
4530+
BPF_PROG_BTF("tp_btf/", BPF_PROG_TYPE_RAW_TRACEPOINT),
45264531
BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP),
45274532
BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT),
45284533
BPF_PROG_SEC("lwt_in", BPF_PROG_TYPE_LWT_IN),
@@ -4627,6 +4632,27 @@ int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
46274632
continue;
46284633
*prog_type = section_names[i].prog_type;
46294634
*expected_attach_type = section_names[i].expected_attach_type;
4635+
if (section_names[i].is_attach_btf) {
4636+
struct btf *btf = bpf_core_find_kernel_btf();
4637+
char raw_tp_btf_name[128] = "btf_trace_";
4638+
char *dst = raw_tp_btf_name + sizeof("btf_trace_") - 1;
4639+
int ret;
4640+
4641+
if (IS_ERR(btf)) {
4642+
pr_warning("vmlinux BTF is not found\n");
4643+
return -EINVAL;
4644+
}
4645+
/* prepend "btf_trace_" prefix per kernel convention */
4646+
strncat(dst, name + section_names[i].len,
4647+
sizeof(raw_tp_btf_name) - (dst - raw_tp_btf_name));
4648+
ret = btf__find_by_name(btf, raw_tp_btf_name);
4649+
btf__free(btf);
4650+
if (ret <= 0) {
4651+
pr_warning("%s is not found in vmlinux BTF\n", dst);
4652+
return -EINVAL;
4653+
}
4654+
*expected_attach_type = ret;
4655+
}
46304656
return 0;
46314657
}
46324658
pr_warning("failed to guess program type based on ELF section name '%s'\n", name);

0 commit comments

Comments
 (0)