On Tue, 2025-07-08 at 22:58 -0700, Eduard Zingerman wrote: [...] > This seems to work: > https://github.com/eddyz87/llvm-project/tree/separate-jumptables-section.1 Pushed an update: - correct offsets computation; - avoid relocations in the .jumptables section. Here is how it looks now (updated session.log attached): foo: # @foo # %bb.0: # %entry w1 = *(u32 *)(r1 + 0) if w1 > 31 goto LBB0_2 # %bb.1: # %entry .LJTI0_0: .reloc 0, FK_SecRel_8, .BPF.JT.0.0 gotox r1 goto LBB0_2 LBB0_7: w1 = 2 goto LBB0_3 ... .Lfunc_end0: .size foo, .Lfunc_end0-foo .section .jumptables,"",@progbits .L0_0_set_7 = LBB0_7-.LJTI0_0 .L0_0_set_2 = LBB0_2-.LJTI0_0 .L0_0_set_8 = LBB0_8-.LJTI0_0 .L0_0_set_9 = LBB0_9-.LJTI0_0 .L0_0_set_10 = LBB0_10-.LJTI0_0 .BPF.JT.0.0: .long .L0_0_set_7 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 ... I think this is a correct form, further changes should be LLVM internal.
$ cat jump-table-test.c int bar(int v); int foo(struct simple_ctx *ctx) { int ret_user; switch (ctx->x) { case 0: ret_user = 2; break; case 11: ret_user = 3; break; case 27: ret_user = 4; break; case 31: ret_user = 5; break; default: ret_user = 19; break; } switch (bar(ret_user)) { case 1: ret_user = 5; break; case 12: ret_user = 7; break; case 27: ret_user = 23; break; case 32: ret_user = 37; break; case 44: ret_user = 77; break; default: ret_user = 11; break; } return ret_user; } $ clang --target=bpf -O2 -S -o - jump-table-test.c .text .globl foo # -- Begin function foo .p2align 3 .type foo,@function foo: # @foo # %bb.0: # %entry w1 = *(u32 *)(r1 + 0) if w1 > 31 goto LBB0_2 # %bb.1: # %entry .LJTI0_0: .reloc 0, FK_SecRel_8, .BPF.JT.0.0 gotox r1 goto LBB0_2 LBB0_7: w1 = 2 goto LBB0_3 LBB0_9: # %sw.bb2 w1 = 4 goto LBB0_3 LBB0_8: # %sw.bb1 w1 = 3 goto LBB0_3 LBB0_10: # %sw.bb3 w1 = 5 goto LBB0_3 LBB0_2: # %sw.default w1 = 19 LBB0_3: # %sw.epilog call bar # kill: def $w0 killed $w0 def $r0 w0 += -1 if w0 > 43 goto LBB0_5 # %bb.4: # %sw.epilog .LJTI0_1: .reloc 0, FK_SecRel_8, .BPF.JT.0.1 gotox r0 goto LBB0_5 LBB0_11: w0 = 5 goto LBB0_6 LBB0_5: # %sw.default9 w0 = 11 goto LBB0_6 LBB0_13: # %sw.bb6 w0 = 23 goto LBB0_6 LBB0_12: # %sw.bb5 w0 = 7 goto LBB0_6 LBB0_14: # %sw.bb7 w0 = 37 goto LBB0_6 LBB0_15: # %sw.bb8 w0 = 77 LBB0_6: # %sw.epilog10 exit .Lfunc_end0: .size foo, .Lfunc_end0-foo .section .jumptables,"",@progbits .L0_0_set_7 = LBB0_7-.LJTI0_0 .L0_0_set_2 = LBB0_2-.LJTI0_0 .L0_0_set_8 = LBB0_8-.LJTI0_0 .L0_0_set_9 = LBB0_9-.LJTI0_0 .L0_0_set_10 = LBB0_10-.LJTI0_0 .BPF.JT.0.0: .long .L0_0_set_7 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_8 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_9 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_2 .long .L0_0_set_10 .size .BPF.JT.0.0, 128 .L0_1_set_11 = LBB0_11-.LJTI0_1 .L0_1_set_5 = LBB0_5-.LJTI0_1 .L0_1_set_12 = LBB0_12-.LJTI0_1 .L0_1_set_13 = LBB0_13-.LJTI0_1 .L0_1_set_14 = LBB0_14-.LJTI0_1 .L0_1_set_15 = LBB0_15-.LJTI0_1 .BPF.JT.0.1: .long .L0_1_set_11 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_12 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_13 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_14 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_5 .long .L0_1_set_15 .size .BPF.JT.0.1, 176 # -- End function .addrsig $ clang --target=bpf -O2 -c -o jump-table-test.o jump-table-test.c $ llvm-readelf -r --symbols --sections jump-table-test.o Section Headers: [Nr] Name Type Address Off Size ES Flg Lk Inf Al [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 [ 1] .strtab STRTAB 0000000000000000 000320 000067 00 0 0 1 [ 2] .text PROGBITS 0000000000000000 000040 0000f0 00 AX 0 0 8 [ 3] .rel.text REL 0000000000000000 0002f0 000030 10 I 6 2 8 [ 4] .jumptables PROGBITS 0000000000000000 000130 000130 00 0 0 1 [ 5] .llvm_addrsig LLVM_ADDRSIG 0000000000000000 000320 000000 00 E 6 0 1 [ 6] .symtab SYMTAB 0000000000000000 000260 000090 18 1 2 8 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), R (retain), p (processor specific) Relocation section '.rel.text' at offset 0x2f0 contains 3 entries: Offset Info Type Symbol's Value Symbol's Name 0000000000000010 0000000300000001 R_BPF_64_64 0000000000000000 .BPF.JT.0.0 0000000000000068 000000040000000a R_BPF_64_32 0000000000000000 bar 0000000000000080 0000000500000001 R_BPF_64_64 0000000000000080 .BPF.JT.0.1 Symbol table '.symtab' contains 6 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS jump-table-test.c 2: 0000000000000000 240 FUNC GLOBAL DEFAULT 2 foo 3: 0000000000000000 128 NOTYPE GLOBAL DEFAULT 4 .BPF.JT.0.0 4: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND bar 5: 0000000000000080 176 NOTYPE GLOBAL DEFAULT 4 .BPF.JT.0.1 $ llvm-objdump --no-show-raw-insn -Sdr jump-table-test.o jump-table-test.o: file format elf64-bpf Disassembly of section .text: 0000000000000000 <foo>: 0: w1 = *(u32 *)(r1 + 0x0) 1: if w1 > 0x1f goto +0xa <foo+0x60> 2: gotox r1 0000000000000010: R_BPF_64_64 .BPF.JT.0.0 3: goto +0x8 <foo+0x60> 4: w1 = 0x2 5: goto +0x7 <foo+0x68> 6: w1 = 0x4 7: goto +0x5 <foo+0x68> 8: w1 = 0x3 9: goto +0x3 <foo+0x68> 10: w1 = 0x5 11: goto +0x1 <foo+0x68> 12: w1 = 0x13 13: call -0x1 0000000000000068: R_BPF_64_32 bar 14: w0 += -0x1 15: if w0 > 0x2b goto +0x4 <foo+0xa0> 16: gotox r0 0000000000000080: R_BPF_64_64 .BPF.JT.0.1 17: goto +0x2 <foo+0xa0> 18: w0 = 0x5 19: goto +0x9 <foo+0xe8> 20: w0 = 0xb 21: goto +0x7 <foo+0xe8> 22: w0 = 0x17 23: goto +0x5 <foo+0xe8> 24: w0 = 0x7 25: goto +0x3 <foo+0xe8> 26: w0 = 0x25 27: goto +0x1 <foo+0xe8> 28: w0 = 0x4d 29: exit