bpf: add support for jal/gotol jump instruction with 32-bit target
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.
This commit is contained in:
parent
338b21b088
commit
c2ca88d74b
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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];
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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:
|
||||
|
@ -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
|
@ -22,4 +22,6 @@
|
||||
jslt %r3,%r4,1f
|
||||
1: jsle %r3,3,1f
|
||||
jsle %r3,%r4,1f
|
||||
1:
|
||||
1: jal 1f
|
||||
jal 1f
|
||||
1:
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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}
|
||||
|
@ -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},
|
||||
|
Loading…
x
Reference in New Issue
Block a user