Re: [PATCH v2 bpf-next] libbpf: support module BTF for BPF_TYPE_ID_TARGET CO-RE relocation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 8 Dec 2020, Andrii Nakryiko wrote:

> When Clang emits ldimm64 instruction for BPF_TYPE_ID_TARGET CO-RE relocation,
> put module BTF FD, containing target type, into upper 32 bits of imm64.
> 
> Because this FD is internal to libbpf, it's very cumbersome to test this in
> selftests. Manual testing was performed with debug log messages sprinkled
> across selftests and libbpf, confirming expected values are substituted.
> Better testing will be performed as part of the work adding module BTF types
> support to  bpf_snprintf_btf() helpers.
> 
> v1->v2:
>   - fix crash on failing to resolve target spec (Alan).
> 
> Cc: Alan Maguire <alan.maguire@xxxxxxxxxx>
> Signed-off-by: Andrii Nakryiko <andrii@xxxxxxxxxx>

Thanks for this!

Can confirm the segmentation fault has gone away. I tested with the
veth_stats_rx program (though will switch to btf_test module later),
and I still see the issue with a local kind of fwd for veth_stats
leading to an inability to find the target kind in the module BTF:

libbpf: sec 'kprobe/veth_stats_rx': found 5 CO-RE relocations
libbpf: prog 'veth_stats_rx': relo #0: kind <target_type_id> (7), spec is 
[20] fwd veth_stats
libbpf: prog 'veth_stats_rx': relo #0: no matching targets found
libbpf: prog 'veth_stats_rx': relo #0: patched insn #3 (LDIMM64) imm64 20 
-> 0
libbpf: prog 'veth_stats_rx': relo #1: kind <target_type_id> (7), spec is 
[20] fwd veth_stats
libbpf: prog 'veth_stats_rx': relo #1: no matching targets found
libbpf: prog 'veth_stats_rx': relo #1: patched insn #5 (LDIMM64) imm64 20 
-> 0

Here's the same debug info with a patch on top of yours that loosens the 
constraints on kind matching such that a fwd local type will match a struct 
target type:

libbpf: prog 'veth_stats_rx': relo #0: kind <target_type_id> (7), spec is 
[20] fwd veth_stats
libbpf: CO-RE relocating [0] fwd veth_stats: found target candidate 
[91516] struct veth_stats in [veth]
libbpf: prog 'veth_stats_rx': relo #0: matching candidate #0 [91516] 
struct veth_stats
libbpf: prog 'veth_stats_rx': relo #0: patched insn #3 (LDIMM64) imm64 20 
-> 450971657596
libbpf: prog 'veth_stats_rx': relo #1: kind <target_type_id> (7), spec is 
[20] fwd veth_stats
libbpf: prog 'veth_stats_rx': relo #1: matching candidate #0 [91516] 
struct veth_stats
libbpf: prog 'veth_stats_rx': relo #1: patched insn #5 (LDIMM64) imm64 20 
-> 450971657596

Patch is below; if it makes sense to support loosening constraints on kind 
matching like this feel free to roll it into your patch or I can send a 
follow-up, whatever's easiest. Thanks!

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 2fb9824..9ead5b3 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -4673,6 +4673,23 @@ static void bpf_core_free_cands(struct 
core_cand_list *ca
        free(cands);
 }
 
+/* module-specific structs may have relo kind set to fwd, so as
+ * well as handling exact matches, a fwd kind has to match
+ * a target struct kind.
+ */
+static bool kind_matches_target(const struct btf_type *local,
+                               const struct btf_type *target)
+{
+       __u8 local_kind = btf_kind(local);
+       __u8 target_kind = btf_kind(target);
+
+       if (local_kind == target_kind)
+               return true;
+       if (local_kind == BTF_KIND_FWD && target_kind == BTF_KIND_STRUCT)
+               return true;
+       return false;
+}
+
 static int bpf_core_add_cands(struct core_cand *local_cand,
                              size_t local_essent_len,
                              const struct btf *targ_btf,
@@ -4689,7 +4706,7 @@ static int bpf_core_add_cands(struct core_cand 
*local_cand
        n = btf__get_nr_types(targ_btf);
        for (i = targ_start_id; i <= n; i++) {
                t = btf__type_by_id(targ_btf, i);
-               if (btf_kind(t) != btf_kind(local_cand->t))
+               if (!kind_matches_target(local_cand->t, t))
                        continue;
 
                targ_name = btf__name_by_offset(targ_btf, t->name_off);
@@ -5057,7 +5074,7 @@ static int bpf_core_types_are_compat(const struct 
btf *loc
        /* caller made sure that names match (ignoring flavor suffix) */
        local_type = btf__type_by_id(local_btf, local_id);
        targ_type = btf__type_by_id(targ_btf, targ_id);
-       if (btf_kind(local_type) != btf_kind(targ_type))
+       if (!kind_matches_target(local_type, targ_type))
                return 0;
 
 recur:
@@ -5070,7 +5087,7 @@ static int bpf_core_types_are_compat(const struct 
btf *loc
        if (!local_type || !targ_type)
                return -EINVAL;
 
-       if (btf_kind(local_type) != btf_kind(targ_type))
+       if (!kind_matches_target(local_type, targ_type))
                return 0;
 
        switch (btf_kind(local_type)) {





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux