Skip to content

Commit c2af6a7

Browse files
committed
libbpf: support llvm-generated indirect jumps
For v5 instruction set, LLVM now is allowed to generate indirect jumps for switch statements. Every such a jump will be accompanied by necessary metadata (enabled by -emit-jump-table-sizes-section). The -bpf-min-jump-table-entries llvm option may be used to control the minimal size of a jump table which will be converted to an indirect jumps. For a given switch the following data will be generated by LLVM: .rodata will contain actual addresses, .llvm_jump_table_sizes and .rel.llvm_jump_table_sizes tables provide meta-data necessary to find and relocate the offsets. The code generated by LLVM for a switch will look, approximately, like this: 0: rX <- jump_table_x[i] 2: rX *= rX 3: gotox rX This code will be rejected by the verifier as is. First transformation required here is that jump_table_x at the insn(0) actually points to the `.rodata` section (map). So for such loads libbpf should create a proper map of type BPF_MAP_TYPE_INSN_ARRAY, using the aforementioned meta-data. Then, in the insn(2) the address in rX gets dereferenced to point to an actual instruction address. (From the verifier's point of view, the rX changes type from PTR_TO_MAP_VALUE to PTR_TO_INSN.) The final line generates an indirect jump. The format of the indirect jump instruction supported by BPF is BPF_JMP|BPF_X|BPF_JA, SRC=0, DST=Rx, off=0, imm=fd(M) and, obviously, the map M must be the same map which was used to init the register rX. This patch implements this in the following, hacky, but so far suitable for all existing use-cases, way. On encountering a `gotox` instruction libbpf tracks back to the previous direct load from map and stores this map file descriptor in the gotox instruction. Signed-off-by: Anton Protopopov <[email protected]>
1 parent ed29b0d commit c2af6a7

File tree

3 files changed

+376
-27
lines changed

3 files changed

+376
-27
lines changed

0 commit comments

Comments
 (0)