aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorJose E. Marchesi <jose.marchesi@oracle.com>2023-07-24 01:15:08 +0200
committerJose E. Marchesi <jose.marchesi@oracle.com>2023-07-24 01:20:03 +0200
commitc2ca88d74ba3618c4aac6744e923c279ca4cb7f1 (patch)
treecdd500a8a997bd1a8f908176d8f5fe4143d0542d /gas/config
parent338b21b0881e16bb7116e4eb5bc41817f805ec23 (diff)
downloadgdb-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.c56
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: