Thread (37 messages) 37 messages, 4 authors, 2021-11-23

Re: [PATCH v3 bpf-next 07/13] libbpf: Use CO-RE in the kernel in light skeleton.

From: Andrii Nakryiko <hidden>
Date: 2021-11-23 00:04:04

On Fri, Nov 19, 2021 at 7:33 PM Alexei Starovoitov
[off-list ref] wrote:
From: Alexei Starovoitov <ast@kernel.org>

Without lskel the CO-RE relocations are processed by libbpf before any other
work is done. Instead, when lskel is needed, remember relocation as RELO_CORE
kind. Then when loader prog is generated for a given bpf program pass CO-RE
relos of that program to gen loader via bpf_gen__record_relo_core(). The gen
loader will remember them as-is and pass it later as-is into the kernel.

The normal libbpf flow is to process CO-RE early before call relos happen. In
case of gen_loader the core relos have to be added to other relos to be copied
together when bpf static function is appended in different places to other main
bpf progs. During the copy the append_subprog_relos() will adjust insn_idx for
normal relos and for RELO_CORE kind too. When that is done each struct
reloc_desc has good relos for specific main prog.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
 tools/lib/bpf/bpf_gen_internal.h |   3 +
 tools/lib/bpf/gen_loader.c       |  41 +++++++++++-
 tools/lib/bpf/libbpf.c           | 108 ++++++++++++++++++++++---------
 3 files changed, 119 insertions(+), 33 deletions(-)
[...]
quoted hunk ↗ jump to hunk
        if (relo->kind != BPF_CORE_TYPE_ID_LOCAL &&
@@ -5653,6 +5679,9 @@ bpf_object__relocate_data(struct bpf_object *obj, struct bpf_program *prog)
                case RELO_CALL:
                        /* handled already */
                        break;
+               case RELO_CORE:
+                       /* will be handled by bpf_program_record_relos() */
+                       break;
                default:
                        pr_warn("prog '%s': relo #%d: bad relo type %d\n",
                                prog->name, i, relo->type);
@@ -6090,6 +6119,35 @@ bpf_object__free_relocs(struct bpf_object *obj)
        }
 }

+static int cmp_relocs(const void *_a, const void *_b)
+{
+       const struct reloc_desc *a = _a;
+       const struct reloc_desc *b = _b;
+
+       if (a->insn_idx != b->insn_idx)
+               return a->insn_idx < b->insn_idx ? -1 : 1;
+
+       /* no two relocations should have the same insn_idx, but ... */
+       if (a->type != b->type)
+               return a->type < b->type ? -1 : 1;
+
+       return 0;
+}
+
+static void bpf_object__sort_relos(struct bpf_object *obj)
+{
+       int i;
+
+       for (i = 0; i < obj->nr_programs; i++) {
+               struct bpf_program *p = &obj->programs[i];
+
+               if (!p->nr_reloc)
+                       continue;
+
+               qsort(p->reloc_desc, p->nr_reloc, sizeof(*p->reloc_desc), cmp_relocs);
+       }
+}
+
 static int
 bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_path)
 {
@@ -6104,6 +6162,8 @@ bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_path)
                                err);
                        return err;
                }
+               if (obj->gen_loader)
+                       bpf_object__sort_relos(obj);
libbpf sorts relos because it does binary search on them (see
find_prog_insn_relo). Kernel doesn't seem to enforce the order of
CO-RE relocations, so there doesn't seem to be a need to sort them. Is
there any reason you wanted to sort them? Does light skeleton's
generated code rely on some ordering? If yes, let's add a small
comment to document this.
        }

        /* Before relocating calls pre-process relocations and mark
[...]
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help