On Sun, Nov 28, 2021 at 6:17 AM Hengqi Chen <hengqi.chen@xxxxxxxxx> wrote: > > Support static initialization of BPF_MAP_TYPE_PROG_ARRAY with a > syntax similar to map-in-map initialization ([0]): > > SEC("socket") > int tailcall_1(void *ctx) > { > return 0; > } > > struct { > __uint(type, BPF_MAP_TYPE_PROG_ARRAY); > __uint(max_entries, 2); > __uint(key_size, sizeof(__u32)); > __array(values, int (void *)); > } prog_array_init SEC(".maps") = { > .values = { > [1] = (void *)&tailcall_1, > }, > }; > > Here's the relevant part of libbpf debug log showing what's > going on with prog-array initialization: > > libbpf: sec '.relsocket': collecting relocation for section(3) 'socket' > libbpf: sec '.relsocket': relo #0: insn #2 against 'prog_array_init' > libbpf: prog 'entry': found map 0 (prog_array_init, sec 4, off 0) for insn #0 > libbpf: .maps relo #0: for 3 value 0 rel->r_offset 32 name 53 ('tailcall_1') > libbpf: .maps relo #0: map 'prog_array_init' slot [1] points to prog 'tailcall_1' > libbpf: map 'prog_array_init': created successfully, fd=5 > libbpf: map 'prog_array_init': slot [1] set to prog 'tailcall_1' fd=6 > > [0] Closes: https://github.com/libbpf/libbpf/issues/354 > > Signed-off-by: Hengqi Chen <hengqi.chen@xxxxxxxxx> > --- > tools/lib/bpf/libbpf.c | 139 ++++++++++++++++++++++++++++++++--------- > 1 file changed, 111 insertions(+), 28 deletions(-) > [...] > - targ_map = bpf_object__find_map_by_name(obj, name); > - if (!targ_map) > - return -ESRCH; > + if (is_map_in_map) { > + targ_map = bpf_object__find_map_by_name(obj, name); > + if (!targ_map) > + return -ESRCH; > + } > + if (is_prog_array) { > + targ_prog = bpf_object__find_program_by_name(obj, name); > + if (!targ_prog) > + return -ESRCH; > + if (targ_prog->sec_idx != sym->st_shndx || > + targ_prog->sec_insn_off * 8 != sym->st_value || > + prog_is_subprog(obj, targ_prog)) { > + pr_warn(".maps relo #%d: '%s' isn't an entry-point BPF program\n", > + i, name); > + return -LIBBPF_ERRNO__RELOC; > + } > + } I've slightly adjusted this part to have an exhaustive if (is_map_in_map) else if (is_prog_array) else { return -EINVAL; }. I've also added an error message when someone is trying to put non-BPF program into BPF_MAP_TYPE_PROG_ARRAY, like this: libbpf: .maps relo #0: 'value' isn't a valid program reference Awesome work, applied to bpf-next, thanks. > > var = btf__type_by_id(obj->btf, vi->type); > def = skip_mods_and_typedefs(obj->btf, var->type, NULL); > @@ -6287,10 +6369,10 @@ static int bpf_object__collect_map_relos(struct bpf_object *obj, > (new_sz - map->init_slots_sz) * host_ptr_sz); > map->init_slots_sz = new_sz; > } > - map->init_slots[moff] = targ_map; > + map->init_slots[moff] = is_map_in_map ? (void *)targ_map : (void *)targ_prog; > > - pr_debug(".maps relo #%d: map '%s' slot [%d] points to map '%s'\n", > - i, map->name, moff, name); > + pr_debug(".maps relo #%d: map '%s' slot [%d] points to %s '%s'\n", > + i, map->name, moff, type, name); > } > > return 0; > @@ -7304,6 +7386,7 @@ int bpf_object__load_xattr(struct bpf_object_load_attr *attr) > err = err ? : bpf_object__create_maps(obj); > err = err ? : bpf_object__relocate(obj, obj->btf_custom_path ? : attr->target_btf_path); > err = err ? : bpf_object__load_progs(obj, attr->log_level); > + err = err ? : bpf_object_init_prog_arrays(obj); > > if (obj->gen_loader) { > /* reset FDs */ > -- > 2.30.2