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 Thu, 2025-07-03 at 11:21 -0700, Eduard Zingerman wrote:

[...]

> > > >   .jumptables
> > > >     <subprog-rel-off-0>
> > > >     <subprog-rel-off-1> | <--- jump table #1 symbol:
> > > >     <subprog-rel-off-2> |        .size = 2   // number of entries in the jump table
> > > >     ...                          .value = 1  // offset within .jumptables
> > > >     <subprog-rel-off-N>                          ^
> > > >                                                  |
> > > >   .text                                          |
> > > >     ...                                          |
> > > >     <insn-N>     <------ relocation referencing -'
> > > >     ...                  jump table #1 symbol

[...]

I think I got it working in:
https://github.com/eddyz87/llvm-project/tree/separate-jumptables-section

Changes on top of Yonghong's work.
An example is in the attachment the gist is:

-------------------------------

$ clang --target=bpf -c -o jump-table-test.o jump-table-test.c
There are 8 section headers, starting at offset 0xaa0:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  ...
  [ 4] .jumptables       PROGBITS        0000000000000000 000220 000260 00      0   0  1
  ...

Symbol table '.symtab' contains 8 entries:
   Num:    Value          Size Type    Bind   Vis       Ndx Name
     ...
     3: 0000000000000000   256 NOTYPE  LOCAL  DEFAULT     4 .BPF.JT.0.0
     4: 0000000000000100   352 NOTYPE  LOCAL  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>:
       ...
       6:       r2 <<= 0x3
       7:       r1 = 0x0 ll
                0000000000000038:  R_BPF_64_64  .jumptables
       9:       r1 += r2
      10:       r1 = *(u64 *)(r1 + 0x0)
      11:       gotox r1
      ...
      34:       r2 <<= 0x3
      35:       r1 = 0x100 ll
                0000000000000118:  R_BPF_64_64  .jumptables
      37:       r1 += r2
      38:       r1 = *(u64 *)(r1 + 0x0)
      39:       gotox r1
      ...

-------------------------------

The changes only touch BPF backend. Can be simplified a bit if I move
MachineFunction::getJTISymbol to TargetLowering in the shared LLVM
parts.
$ cat jump-table-test.c
struct simple_ctx { int x; };

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 -c -o jump-table-test.o jump-table-test.c
There are 8 section headers, starting at offset 0xaa0:

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 000a31 00006b 00      0   0  1
  [ 2] .text             PROGBITS        0000000000000000 000040 0001e0 00  AX  0   0  8
  [ 3] .rel.text         REL             0000000000000000 000540 000030 10   I  7   2  8
  [ 4] .jumptables       PROGBITS        0000000000000000 000220 000260 00      0   0  1
  [ 5] .rel.jumptables   REL             0000000000000000 000570 0004c0 10   I  7   4  8
  [ 6] .llvm_addrsig     LLVM_ADDRSIG    0000000000000000 000a30 000001 00   E  7   0  1
  [ 7] .symtab           SYMTAB          0000000000000000 000480 0000c0 18      1   6  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)

Symbol table '.symtab' contains 8 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     0 SECTION LOCAL  DEFAULT     2 .text
     3: 0000000000000000   256 NOTYPE  LOCAL  DEFAULT     4 .BPF.JT.0.0
     4: 0000000000000100   352 NOTYPE  LOCAL  DEFAULT     4 .BPF.JT.0.1
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT     4 .jumptables
     6: 0000000000000000   480 FUNC    GLOBAL DEFAULT     2 foo
     7: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT   UND bar

$ 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:	*(u64 *)(r10 - 0x8) = r1
       1:	r1 = *(u64 *)(r10 - 0x8)
       2:	w1 = *(u32 *)(r1 + 0x0)
       3:	*(u64 *)(r10 - 0x18) = r1
       4:	if w1 > 0x1f goto +0x13 <foo+0xc0>
       5:	r2 = *(u64 *)(r10 - 0x18)
       6:	r2 <<= 0x3
       7:	r1 = 0x0 ll
		0000000000000038:  R_BPF_64_64	.jumptables
       9:	r1 += r2
      10:	r1 = *(u64 *)(r1 + 0x0)
      11:	gotox r1
      12:	w1 = 0x2
      13:	*(u32 *)(r10 - 0xc) = w1
      14:	goto +0xc <foo+0xd8>
      15:	w1 = 0x3
      16:	*(u32 *)(r10 - 0xc) = w1
      17:	goto +0x9 <foo+0xd8>
      18:	w1 = 0x4
      19:	*(u32 *)(r10 - 0xc) = w1
      20:	goto +0x6 <foo+0xd8>
      21:	w1 = 0x5
      22:	*(u32 *)(r10 - 0xc) = w1
      23:	goto +0x3 <foo+0xd8>
      24:	w1 = 0x13
      25:	*(u32 *)(r10 - 0xc) = w1
      26:	goto +0x0 <foo+0xd8>
      27:	w1 = *(u32 *)(r10 - 0xc)
      28:	call -0x1
		00000000000000e0:  R_BPF_64_32	bar
      29:	w0 += -0x1
      30:	w1 = w0
      31:	*(u64 *)(r10 - 0x20) = r1
      32:	if w0 > 0x2b goto +0x16 <foo+0x1b8>
      33:	r2 = *(u64 *)(r10 - 0x20)
      34:	r2 <<= 0x3
      35:	r1 = 0x100 ll
		0000000000000118:  R_BPF_64_64	.jumptables
      37:	r1 += r2
      38:	r1 = *(u64 *)(r1 + 0x0)
      39:	gotox r1
      40:	w1 = 0x5
      41:	*(u32 *)(r10 - 0xc) = w1
      42:	goto +0xf <foo+0x1d0>
      43:	w1 = 0x7
      44:	*(u32 *)(r10 - 0xc) = w1
      45:	goto +0xc <foo+0x1d0>
      46:	w1 = 0x17
      47:	*(u32 *)(r10 - 0xc) = w1
      48:	goto +0x9 <foo+0x1d0>
      49:	w1 = 0x25
      50:	*(u32 *)(r10 - 0xc) = w1
      51:	goto +0x6 <foo+0x1d0>
      52:	w1 = 0x4d
      53:	*(u32 *)(r10 - 0xc) = w1
      54:	goto +0x3 <foo+0x1d0>
      55:	w1 = 0xb
      56:	*(u32 *)(r10 - 0xc) = w1
      57:	goto +0x0 <foo+0x1d0>
      58:	w0 = *(u32 *)(r10 - 0xc)
      59:	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