Re: [RFC bpf-next 8/9] libbpf: support llvm-generated indirect jumps

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux