For raw tracepoint program types libbpf will try to find
btf_id of raw tracepoint in vmlinux's BTF.
It's a responsiblity of bpf program author to annotate the program
with SEC("raw_tracepoint/name") where "name" is a valid raw tracepoint.
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.

Signed-off-by: Alexei Starovoitov <a...@kernel.org>
---
 tools/lib/bpf/bpf.c    |  3 +++
 tools/lib/bpf/libbpf.c | 17 +++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index cbb933532981..79046067720f 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -228,6 +228,9 @@ int bpf_load_program_xattr(const struct 
bpf_load_program_attr *load_attr,
        memset(&attr, 0, sizeof(attr));
        attr.prog_type = load_attr->prog_type;
        attr.expected_attach_type = load_attr->expected_attach_type;
+       if (attr.prog_type == BPF_PROG_TYPE_RAW_TRACEPOINT)
+               /* expected_attach_type is ignored for tracing progs */
+               attr.attach_btf_id = attr.expected_attach_type;
        attr.insn_cnt = (__u32)load_attr->insns_cnt;
        attr.insns = ptr_to_u64(load_attr->insns);
        attr.license = ptr_to_u64(load_attr->license);
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index a02cdedc4e3f..8bf30a67428c 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -4586,6 +4586,23 @@ int libbpf_prog_type_by_name(const char *name, enum 
bpf_prog_type *prog_type,
                        continue;
                *prog_type = section_names[i].prog_type;
                *expected_attach_type = section_names[i].expected_attach_type;
+               if (*prog_type == BPF_PROG_TYPE_RAW_TRACEPOINT) {
+                       struct btf *btf = bpf_core_find_kernel_btf();
+                       char raw_tp_btf_name[128] = "btf_trace_";
+                       char *dst = raw_tp_btf_name + sizeof("btf_trace_") - 1;
+                       int ret;
+
+                       if (IS_ERR(btf))
+                               /* lack of kernel BTF is not a failure */
+                               return 0;
+                       /* prepend "btf_trace_" prefix per kernel convention */
+                       strncat(dst, name + section_names[i].len,
+                               sizeof(raw_tp_btf_name) - (dst - 
raw_tp_btf_name));
+                       ret = btf__find_by_name(btf, raw_tp_btf_name);
+                       if (ret > 0)
+                               *expected_attach_type = ret;
+                       btf__free(btf);
+               }
                return 0;
        }
        pr_warning("failed to guess program type based on ELF section name 
'%s'\n", name);
-- 
2.23.0

Reply via email to