On 25/08/20 05:20PM, Andrii Nakryiko wrote: > On Sat, Aug 16, 2025 at 11:02 AM Anton Protopopov > <a.s.protopopov@xxxxxxxxx> wrote: > > > > For v5 instruction set, LLVM now is allowed to generate indirect > > jumps for switch statements and for 'goto *rX' assembly. Every such a > > jump will be accompanied by necessary metadata, e.g. (`llvm-objdump > > -Sr ...`): > > > > 0: r2 = 0x0 ll > > 0000000000000030: R_BPF_64_64 BPF.JT.0.0 > > > > Here BPF.JT.1.0 is a symbol residing in the .jumptables section: > > > > Symbol table: > > 4: 0000000000000000 240 OBJECT GLOBAL DEFAULT 4 BPF.JT.0.0 > > > > The -bpf-min-jump-table-entries llvm option may be used to control > > the minimal size of a switch which will be converted to an indirect > > jumps. > > > > The code generated by LLVM for a switch will look, approximately, > > like this: > > > > 0: rX <- jump_table_x[i] > > 2: rX <<= 3 > > 3: gotox *rX > > > > Right now there is no robust way to associate the jump with the > > corresponding map, so libbpf doesn't insert map file descriptor > > inside the gotox instruction. > [...] > > > + err = bpf_map_update_elem(map_fd, &i, &val, 0); > > + if (err) { > > + close(map_fd); > > + return err; > > + } > > + } > > + > > + err = bpf_map_freeze(map_fd); > > + if (err) { > > + close(map_fd); > > + return err; > > + } > > + > > + return map_fd; > > +} > > + > > +static int subprog_insn_off(struct bpf_program *prog, int insn_idx) > > +{ > > + int i; > > + > > + for (i = prog->subprog_cnt - 1; i >= 0; i--) > > + if (insn_idx >= prog->subprog_offset[i]) > > + return prog->subprog_offset[i] - prog->subprog_sec_offst[i]; > > I feel like this whole subprog_offset and subprog_sec_offst shouldn't > be even necessary. > > Check bpf_object__relocate(). I'm not sure why this was done this way > that we go across all programs in phases, doing code relocation first, > then data relocation later (across all programs again). I might be > forgetting some details, but if we change this to do all the > relocation for each program one at a time, then all this information > that you explicitly record is already recorded in > subprog->sub_insn_off and you can use it until we start relocating > another entry-point program. Can you give it a try? > > So basically the structure will be: > > for (i = 0; i < obj->nr_programs; i++) { > prog = ... > if (prog_is_subprog(...)) > continue; > if (!prog->autoload) > continue; > bpf_object__relocate_calls() > /* that exception callback handling */ > bpf_object__relocate_data() > bpf_program_fixup_func_info() > } > > It feels like this should work because there cannot be > interdependencies between entry programs. So turns out that the reason why it is separate is given in the commit which introduced this separation, see b12688267280b223256c8cf912486577d3adce25 (So I kept this part of my patch the same in v2.) [...]