diff options
author | Jose E. Marchesi <jose.marchesi@oracle.com> | 2023-07-24 01:15:08 +0200 |
---|---|---|
committer | Jose E. Marchesi <jose.marchesi@oracle.com> | 2023-07-24 01:20:03 +0200 |
commit | c2ca88d74ba3618c4aac6744e923c279ca4cb7f1 (patch) | |
tree | cdd500a8a997bd1a8f908176d8f5fe4143d0542d /gas/config | |
parent | 338b21b0881e16bb7116e4eb5bc41817f805ec23 (diff) | |
download | gdb-c2ca88d74ba3618c4aac6744e923c279ca4cb7f1.zip gdb-c2ca88d74ba3618c4aac6744e923c279ca4cb7f1.tar.gz gdb-c2ca88d74ba3618c4aac6744e923c279ca4cb7f1.tar.bz2 |
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.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-bpf.c | 56 |
1 files changed, 34 insertions, 22 deletions
diff --git a/gas/config/tc-bpf.c b/gas/config/tc-bpf.c index 7a54fac..c56b8fe 100644 --- a/gas/config/tc-bpf.c +++ b/gas/config/tc-bpf.c @@ -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: |