bpf: add support for jal/gotol jump instruction with 32-bit target
authorJose E. Marchesi <jose.marchesi@oracle.com>
Sun, 23 Jul 2023 23:15:08 +0000 (01:15 +0200)
committerJose E. Marchesi <jose.marchesi@oracle.com>
Sun, 23 Jul 2023 23:20:03 +0000 (01:20 +0200)
This patch adds support for the V4 BPF instruction jal/gotol, which is
like ja/goto but it supports a signed 32-bit PC-relative (in number of
64-bit words minus one) target operand instead of the 16-bit signed
operand of the other instruction.  This greatly increases the jump
range in BPF programs.

Tested in bpf-unkown-none.

bfd/ChangeLog:

2023-07-24  Jose E. Marchesi  <jose.marchesi@oracle.com>

* reloc.c: New reloc BFD_RELOC_BPF_DISPCALL32.
* elf64-bpf.c (bpf_reloc_type_lookup): Handle the new reloc.
* libbfd.h (bfd_reloc_code_real_names): Regenerate.

gas/ChangeLog:

2023-07-24  Jose E. Marchesi  <jose.marchesi@oracle.com>

* config/tc-bpf.c (struct bpf_insn): New field `id'.
(md_assemble): Save the ids of successfully parsed instructions
and use the new BFD_RELOC_BPF_DISPCALL32 whenever appropriate.
(md_apply_fix): Adapt to the new BFD reloc.
* testsuite/gas/bpf/jump.s: Test JAL.
* testsuite/gas/bpf/jump.d: Likewise.
* testsuite/gas/bpf/jump-pseudoc.d: Likewise.
* testsuite/gas/bpf/jump-be.d: Likewise.
* testsuite/gas/bpf/jump-be-pseudoc.d: Likewise.
* doc/c-bpf.texi (BPF Instructions): Document new instruction
jal/gotol.
Document new operand type disp32.

include/ChangeLog:

2023-07-24  Jose E. Marchesi  <jose.marchesi@oracle.com>

* opcode/bpf.h (enum bpf_insn_id): Add entry BPF_INSN_JAL.
(enum bpf_insn_id): Remove spurious entry BPF_INSN_CALLI.

opcodes/ChangeLog:

2023-07-23  Jose E. Marchesi  <jose.marchesi@oracle.com>

* bpf-opc.c (bpf_opcodes): Add entry for jal.

18 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf64-bpf.c
bfd/libbfd.h
bfd/reloc.c
gas/ChangeLog
gas/config/tc-bpf.c
gas/doc/c-bpf.texi
gas/testsuite/gas/bpf/jump-be-pseudoc.d
gas/testsuite/gas/bpf/jump-be.d
gas/testsuite/gas/bpf/jump-pseudoc.d
gas/testsuite/gas/bpf/jump-pseudoc.s
gas/testsuite/gas/bpf/jump.d
gas/testsuite/gas/bpf/jump.s
include/ChangeLog
include/opcode/bpf.h
opcodes/ChangeLog
opcodes/bpf-opc.c

index 553dea5d0b00719257efcddffadd8213453e04ae..db032df5ac2c04e541ad0ad5769f1c30356de92b 100644 (file)
@@ -1,3 +1,9 @@
+2023-07-24  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+       * reloc.c: New reloc BFD_RELOC_BPF_DISPCALL32.
+       * elf64-bpf.c (bpf_reloc_type_lookup): Handle the new reloc.
+       * libbfd.h (bfd_reloc_code_real_names): Regenerate.
+
 2023-07-09  Fangrui Song  <maskray@google.com>
 
        PR 30592
index ba7440c2768d2e102a504484e8a2516794bdadbe..5f49807d7f20e7ec2ab5b8db8b9b7ec7ee91997a 100644 (file)
@@ -7148,6 +7148,7 @@ assembler and not (currently) written to any object files.  */
 /* Linux eBPF relocations.  */
   BFD_RELOC_BPF_64,
   BFD_RELOC_BPF_DISP32,
+  BFD_RELOC_BPF_DISPCALL32,
   BFD_RELOC_BPF_DISP16,
 
 /* Adapteva EPIPHANY - 8 bit signed pc-relative displacement  */
index 23ede4e5d96be5f0daac821986a20051ea92012b..aefad7da5ac0708797f7a0d55a88199eb719e984 100644 (file)
@@ -88,6 +88,7 @@ bpf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
     case BFD_RELOC_BPF_64:
       return &bpf_elf_howto_table[ (int) R_BPF_64_64_IDX];
     case BFD_RELOC_BPF_DISP32:
+    case BFD_RELOC_BPF_DISPCALL32:
       return &bpf_elf_howto_table[ (int) R_BPF_64_32_IDX];
     case BFD_RELOC_BPF_DISP16:
       return &bpf_elf_howto_table[ (int) R_BPF_GNU_64_16_IDX];
index 5dbb0871607512a523f063a6af8778768e3c697e..1fc88a888612b4c673dc0687389ea6945bceb163 100644 (file)
@@ -3346,6 +3346,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_TILEGX_IMM8_Y1_TLS_ADD",
   "BFD_RELOC_BPF_64",
   "BFD_RELOC_BPF_DISP32",
+  "BFD_RELOC_BPF_DISPCALL32",
   "BFD_RELOC_BPF_DISP16",
   "BFD_RELOC_EPIPHANY_SIMM8",
   "BFD_RELOC_EPIPHANY_SIMM24",
index e71a510e26ce7a600b4e6f6d6848256f10a2cfe4..07d35e45c8be20e59138cbad041fcc8b2b86320a 100644 (file)
@@ -7753,6 +7753,8 @@ ENUM
   BFD_RELOC_BPF_64
 ENUMX
   BFD_RELOC_BPF_DISP32
+ENUMX
+  BFD_RELOC_BPF_DISPCALL32
 ENUMX
   BFD_RELOC_BPF_DISP16
 ENUMDOC
index f91c04572ecb680807a25764aba27b6905dc612e..b45fd9fa8bd267298e12ffeda243f72ed30f5b36 100644 (file)
@@ -1,3 +1,18 @@
+2023-07-24  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+       * config/tc-bpf.c (struct bpf_insn): New field `id'.
+       (md_assemble): Save the ids of successfully parsed instructions
+       and use the new BFD_RELOC_BPF_DISPCALL32 whenever appropriate.
+       (md_apply_fix): Adapt to the new BFD reloc.
+       * testsuite/gas/bpf/jump.s: Test JAL.
+       * testsuite/gas/bpf/jump.d: Likewise.
+       * testsuite/gas/bpf/jump-pseudoc.d: Likewise.
+       * testsuite/gas/bpf/jump-be.d: Likewise.
+       * testsuite/gas/bpf/jump-be-pseudoc.d: Likewise.
+       * doc/c-bpf.texi (BPF Instructions): Document new instruction
+       jal/gotol.
+       Document new operand type disp32.
+
 2023-07-21  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
        * testsuite/gas/bpf/mem.s: Add signed load instructions.
index 7a54faccb59d09b8e96f7ea63692a25888b58b2e..c56b8fe984f9038e1d35a7e15ebd1b311f9db5fa 100644 (file)
@@ -33,6 +33,7 @@
 
 struct bpf_insn
 {
+  enum bpf_insn_id id;
   int size; /* Instruction size in bytes.  */
   bpf_insn_word opcode;
   uint8_t dst;
@@ -375,30 +376,35 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
          minus one.  */
       *valP = (((long) (*valP)) - 8) / 8;
       break;
+    case BFD_RELOC_BPF_DISPCALL32:
     case BFD_RELOC_BPF_DISP32:
-      /* eBPF supports two kind of CALL instructions: the so called
-         pseudo calls ("bpf to bpf") and external calls ("bpf to
-         kernel").
-
-         Both kind of calls use the same instruction (CALL).  However,
-         external calls are constructed by passing a constant argument
-         to the instruction, whereas pseudo calls result from
-         expressions involving symbols.  In practice, instructions
-         requiring a fixup are interpreted as pseudo-calls.  If we are
-         executing this code, this is a pseudo call.
-
-         The kernel expects for pseudo-calls to be annotated by having
-         BPF_PSEUDO_CALL in the SRC field of the instruction.  But
-         beware the infamous nibble-swapping of eBPF and take
-         endianness into account here.
-
-         Note that the CALL instruction has only one operand, so
-         this code is executed only once per instruction.  */
-      md_number_to_chars (where + 1, target_big_endian ? 0x01 : 0x10, 1);
-
       /* Convert from bytes to number of 64-bit words to the target,
          minus one.  */
       *valP = (((long) (*valP)) - 8) / 8;
+
+      if (fixP->fx_r_type == BFD_RELOC_BPF_DISPCALL32)
+        {
+          /* eBPF supports two kind of CALL instructions: the so
+             called pseudo calls ("bpf to bpf") and external calls
+             ("bpf to kernel").
+
+             Both kind of calls use the same instruction (CALL).
+             However, external calls are constructed by passing a
+             constant argument to the instruction, whereas pseudo
+             calls result from expressions involving symbols.  In
+             practice, instructions requiring a fixup are interpreted
+             as pseudo-calls.  If we are executing this code, this is
+             a pseudo call.
+
+             The kernel expects for pseudo-calls to be annotated by
+             having BPF_PSEUDO_CALL in the SRC field of the
+             instruction.  But beware the infamous nibble-swapping of
+             eBPF and take endianness into account here.
+
+             Note that the CALL instruction has only one operand, so
+             this code is executed only once per instruction.  */
+          md_number_to_chars (where + 1, target_big_endian ? 0x01 : 0x10, 1);
+        }
       break;
     case BFD_RELOC_16_PCREL:
       /* Convert from bytes to number of 64-bit words to the target,
@@ -434,6 +440,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
           md_number_to_chars (where + 2, (uint16_t) *valP, 2);
           break;
         case BFD_RELOC_BPF_DISP32:
+        case BFD_RELOC_BPF_DISPCALL32:
           md_number_to_chars (where + 4, (uint32_t) *valP, 4);
           break;
         case BFD_RELOC_16_PCREL:
@@ -852,6 +859,7 @@ md_assemble (char *str ATTRIBUTE_UNUSED)
 
       return;
     }
+  insn.id = opcode->id;
   insn.opcode = opcode->opcode;
 
 #undef PARSE_ERROR
@@ -1044,8 +1052,12 @@ md_assemble (char *str ATTRIBUTE_UNUSED)
             {
               reloc_howto_type *reloc_howto;
               int size;
+              unsigned int bfd_reloc
+                = (insn.id == BPF_INSN_CALL
+                   ? BFD_RELOC_BPF_DISPCALL32
+                   : BFD_RELOC_BPF_DISP32);
 
-              reloc_howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_BPF_DISP32);
+              reloc_howto = bfd_reloc_type_lookup (stdoutput, bfd_reloc);
               if (!reloc_howto)
                 abort ();
 
@@ -1053,7 +1065,7 @@ md_assemble (char *str ATTRIBUTE_UNUSED)
 
               fix_new_exp (frag_now, this_frag - frag_now->fr_literal,
                            size, &insn.disp32, reloc_howto->pc_relative,
-                           BFD_RELOC_BPF_DISP32);
+                           bfd_reloc);
               break;
             }
           default:
index bebf760f91fc0f04cd76125359b72a0c31201272..d4fd1819dbe583f996b8c96c25ace802d41c6b17 100644 (file)
@@ -160,6 +160,9 @@ Signed 16-bit immediate representing an offset in bytes.
 @item disp16
 Signed 16-bit immediate representing a displacement to a target,
 measured in number of 64-bit words @emph{minus one}.
+@item disp32
+Signed 32-bit immediate representing a displacement to a target,
+measured in number of 64-bit words @emph{minus one}.
 @item imm32
 Signed 32-bit immediate.
 @item imm64
@@ -555,6 +558,10 @@ holds true.
 @itemx goto disp16
 Jump-always.
 
+@item jal disp32
+@itemx gotol disp32
+Jump-always, long range.
+
 @item jeq rd, rs, disp16
 @itemx jeq rd, imm32, disp16
 @itemx if rd == rs goto disp16
index 3874d58f73a7d77847de4cc57120ecc89c94c087..827731182c114d241cebb4dc619e44fee42a01d2 100644 (file)
@@ -30,3 +30,5 @@ Disassembly of section .text:
   98:  cd 34 00 00 00 00 00 00         if r3s<r4 goto 0
   a0:  d5 30 00 01 00 00 00 03         if r3s<=3 goto 1
   a8:  dd 34 00 00 00 00 00 00         if r3s<=r4 goto 0
+  b0:  06 00 00 00 00 00 00 01         gotol 1
+  b8:  06 00 00 00 00 00 00 00         gotol 0
index 7c8a765ddcf9d23713eca2b8c9652c6bb72dd847..fffe1e952d7935f290e554194322562077a2509f 100644 (file)
@@ -30,3 +30,5 @@ Disassembly of section .text:
   98:  cd 34 00 00 00 00 00 00         jslt %r3,%r4,0
   a0:  d5 30 00 01 00 00 00 03         jsle %r3,3,1
   a8:  dd 34 00 00 00 00 00 00         jsle %r3,%r4,0
+  b0:  06 00 00 00 00 00 00 01         jal 1
+  b8:  06 00 00 00 00 00 00 00         jal 0
index 644d2be30b7cbb48eeb94d9047583dfad556165d..9b68108d9eee11db722695649c29e478e132a53e 100644 (file)
@@ -30,3 +30,5 @@ Disassembly of section .text:
   98:  cd 43 00 00 00 00 00 00         if r3s<r4 goto 0
   a0:  d5 03 01 00 03 00 00 00         if r3s<=3 goto 1
   a8:  dd 43 00 00 00 00 00 00         if r3s<=r4 goto 0
+  b0:  06 00 00 00 01 00 00 00         gotol 1
+  b8:  06 00 00 00 00 00 00 00         gotol 0
\ No newline at end of file
index 1331bdad307c65712858705175061604b7f1ba05..9f860807a3e1d78462e7e860a80a44b0d7872440 100644 (file)
@@ -22,4 +22,6 @@
         if r3 s< r4 goto 1f
 1:      if r3 s<= 3 goto 1f
         if r3 s<= r4 goto 1f
+1:      gotol 1f
+        gotol 1f
 1:
index 742610a8ab21592beb6c71da24641413d6f8f69b..4da37278cf87e79d77066def8cdc302cb9be923c 100644 (file)
@@ -30,3 +30,5 @@ Disassembly of section .text:
   98:  cd 43 00 00 00 00 00 00         jslt %r3,%r4,0
   a0:  d5 03 01 00 03 00 00 00         jsle %r3,3,1
   a8:  dd 43 00 00 00 00 00 00         jsle %r3,%r4,0
+  b0:  06 00 00 00 01 00 00 00         jal 1
+  b8:  06 00 00 00 00 00 00 00         jal 0
\ No newline at end of file
index aae4295e1603628df94416aa324de8745f29698d..c3d36bddeec885cbc823e925a80bfea62eb76bd2 100644 (file)
@@ -22,4 +22,6 @@
         jslt %r3,%r4,1f
 1:      jsle %r3,3,1f
         jsle %r3,%r4,1f
-1:      
+1:      jal 1f
+        jal 1f
+1:
index ccf16619d1a3607fbc10db3e42c553ccd3363543..8cad8e2ea7a1c8375ccc6dccb42e6fff385a938b 100644 (file)
@@ -1,3 +1,8 @@
+2023-07-24  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+       * opcode/bpf.h (enum bpf_insn_id): Add entry BPF_INSN_JAL.
+       (enum bpf_insn_id): Remove spurious entry BPF_INSN_CALLI.
+
 2023-07-21  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
        * opcode/bpf.h (enum bpf_insn_id): Add entries for signed load
index a491df6fbdfdd0ad5b2390189e5f84f638d6caa8..dc1b6e7ae57eb8bbb215d5ce3b79f503e44c3c2f 100644 (file)
@@ -201,7 +201,8 @@ enum bpf_insn_id
   BPF_INSN_JEQI, BPF_INSN_JGTI, BPF_INSN_JSGTI,
   BPF_INSN_JGEI, BPF_INSN_JSGEI, BPF_INSN_JLTI, BPF_INSN_JSLTI,
   BPF_INSN_JSLEI, BPF_INSN_JLEI, BPF_INSN_JSETI, BPF_INSN_JNEI,
-  BPF_INSN_CALLI,
+  /* jump-always with 32-bit offset.  */
+  BPF_INSN_JAL,
   /* 32-bit compare-and-jump instructions (reg OP reg.)  */
   BPF_INSN_JEQ32R, BPF_INSN_JGT32R, BPF_INSN_JSGT32R,
   BPF_INSN_JGE32R, BPF_INSN_JSGE32R, BPF_INSN_JLT32R, BPF_INSN_JSLT32R,
index f88e9c846fb4447407715a603562a2626a7d8bb5..d97eb389c9f3169f41da06221bffebc43c7e56d0 100644 (file)
@@ -1,3 +1,7 @@
+2023-07-23  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+       * bpf-opc.c (bpf_opcodes): Add entry for jal.
+
 2023-07-21  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
        * bpf-opc.c (bpf_opcodes): Add entries for LDXS{B,W,H,DW}
index efd32577821d21f06b8a34392bdc8dcee8778d3d..4ffd86719a7ffff0fe6842901bf8afdb6c70324c 100644 (file)
@@ -303,6 +303,10 @@ const struct bpf_opcode bpf_opcodes[] =
   {BPF_INSN_JNEI, "jne%W%dr , %i32 , %d16", "if%w%dr != %i32%wgoto%w%d16",
    BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JNE|BPF_SRC_K},
 
+  /* 32-bit jump-always.  */
+  {BPF_INSN_JAL, "jal%W%d32", "gotol%w%d32",
+   BPF_V4, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JA|BPF_SRC_K},
+
   /* 32-bit compare-and-jump instructions (reg OP reg).  */
   {BPF_INSN_JEQ32R, "jeq32%W%dr , %sr , %d16", "if%w%dw == %sw%wgoto%w%d16",
    BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JEQ|BPF_SRC_X},