bpf: gas: consolidate handling of immediate overflows

This commit changes the BPF GAS port in order to handle immediate
overflows the same way than the clang BPF assembler:

- For an immediate field of N bits, any written number (positive or
  negative) whose two's complement encoding fit in N its is accepted.
  This means that -2 is the same than 0xffffffe.  It is up to the
  instructions to decide how to interpret the encoded value.

- Immediate fields in jump instructions are no longer relaxed.
  Relaxing to jump instructions with wider range is only performed
  when expressions are involved.

- The manual is updated to document this, and testsuite adapted
  accordingly.

Tested in x86_64-linux-gnu host, bpf-unknown-none target.

gas/ChangeLog:

2023-08-17  Jose E. Marchesi  <jose.marchesi@oracle.com>

	* config/tc-bpf.c (check_immediate_overflow): New function.
	(encode_insn): Use check_immediate_overflow.
	(md_assemble): Do not relax instructions with
	constant disp16 fields.
	* doc/c-bpf.texi (BPF Instructions): Add note about how numerical
	literal values are interpreted for instruction immediate operands.
	* testsuite/gas/bpf/disp16-overflow.s: Adapt accordingly.
	* testsuite/gas/bpf/jump-relax-jump.s: Likewise.
	* testsuite/gas/bpf/jump-relax-jump.d: Likewise.
	* testsuite/gas/bpf/jump-relax-jump-be.d: Likewise.
	* testsuite/gas/bpf/jump-relax-ja.s: Likewise.
	* testsuite/gas/bpf/jump-relax-ja.d: Likewise.
	* testsuite/gas/bpf/jump-relax-ja-be.d: Likewise.
	* testsuite/gas/bpf/disp16-overflow-relax.l: Likewise.
	* testsuite/gas/bpf/imm32-overflow.s: Likewise.
	* testsuite/gas/bpf/disp32-overflow.s: Likewise.
	* testsuite/gas/bpf/disp16-overflow.l: Likewise.
	* testsuite/gas/bpf/disp32-overflow.l: Likewise.
	* testsuite/gas/bpf/imm32-overflow.l: Likewise.
	* testsuite/gas/bpf/offset16-overflow.l: Likewise.
This commit is contained in:
Jose E. Marchesi 2023-08-17 09:38:37 +02:00
parent 646657284f
commit 5be1b78727
20 changed files with 96 additions and 67 deletions

View File

@ -1,3 +1,26 @@
2023-08-17 Jose E. Marchesi <jose.marchesi@oracle.com>
* config/tc-bpf.c (check_immediate_overflow): New function.
(encode_insn): Use check_immediate_overflow.
(md_assemble): Do not relax instructions with
constant disp16 fields.
* doc/c-bpf.texi (BPF Instructions): Add note about how numerical
literal values are interpreted for instruction immediate operands.
* testsuite/gas/bpf/disp16-overflow.s: Adapt accordingly.
* testsuite/gas/bpf/jump-relax-jump.s: Likewise.
* testsuite/gas/bpf/jump-relax-jump.d: Likewise.
* testsuite/gas/bpf/jump-relax-jump-be.d: Likewise.
* testsuite/gas/bpf/jump-relax-ja.s: Likewise.
* testsuite/gas/bpf/jump-relax-ja.d: Likewise.
* testsuite/gas/bpf/jump-relax-ja-be.d: Likewise.
* testsuite/gas/bpf/disp16-overflow-relax.l: Likewise.
* testsuite/gas/bpf/imm32-overflow.s: Likewise.
* testsuite/gas/bpf/disp32-overflow.s: Likewise.
* testsuite/gas/bpf/disp16-overflow.l: Likewise.
* testsuite/gas/bpf/disp32-overflow.l: Likewise.
* testsuite/gas/bpf/imm32-overflow.l: Likewise.
* testsuite/gas/bpf/offset16-overflow.l: Likewise.
2023-07-30 Jose E. Marchesi <jose.marchesi@oracle.com>
* config/tc-bpf.h (elf_tc_final_processing): Define.

View File

@ -286,6 +286,26 @@ signed_overflow (offsetT value, unsigned bits)
return (value < -lim || value >= lim);
}
/* Return non-zero if the two's complement encoding of VALUE would
overflow an immediate field of width BITS bits. */
static bool
immediate_overflow (int64_t value, unsigned bits)
{
if (value < 0)
return signed_overflow (value, bits);
else
{
valueT lim;
if (bits >= sizeof (valueT) * 8)
return false;
lim = (valueT) 1 << bits;
return ((valueT) value >= lim);
}
}
/* Functions concerning relocs. */
@ -379,7 +399,7 @@ tc_gen_reloc (asection *sec ATTRIBUTE_UNUSED, fixS *fixP)
#define RELAX_BRANCH_UNCOND(i) (((i) & 1) != 0)
/* Compute the length of a branch seuqence, and adjust the stored
/* Compute the length of a branch sequence, and adjust the stored
length accordingly. If FRAG is NULL, the worst-case length is
returned. */
@ -854,7 +874,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
immediates are encoded as zeroes. */
static void
encode_insn (struct bpf_insn *insn, char *bytes, int relaxed)
encode_insn (struct bpf_insn *insn, char *bytes,
int relaxed ATTRIBUTE_UNUSED)
{
uint8_t src, dst;
@ -911,8 +932,8 @@ encode_insn (struct bpf_insn *insn, char *bytes, int relaxed)
{
int64_t imm = insn->imm32.X_add_number;
if (signed_overflow (imm, 32))
as_bad (_("signed immediate out of range, shall fit in 32 bits"));
if (immediate_overflow (imm, 32))
as_bad (_("immediate out of range, shall fit in 32 bits"));
else
encode_int32 (insn->imm32.X_add_number, bytes + 4);
}
@ -921,8 +942,8 @@ encode_insn (struct bpf_insn *insn, char *bytes, int relaxed)
{
int64_t disp = insn->disp32.X_add_number;
if (signed_overflow (disp, 32))
as_bad (_("signed pc-relative offset out of range, shall fit in 32 bits"));
if (immediate_overflow (disp, 32))
as_bad (_("pc-relative offset out of range, shall fit in 32 bits"));
else
encode_int32 (insn->disp32.X_add_number, bytes + 4);
}
@ -931,8 +952,8 @@ encode_insn (struct bpf_insn *insn, char *bytes, int relaxed)
{
int64_t offset = insn->offset16.X_add_number;
if (signed_overflow (offset, 16))
as_bad (_("signed pc-relative offset out of range, shall fit in 16 bits"));
if (immediate_overflow (offset, 16))
as_bad (_("pc-relative offset out of range, shall fit in 16 bits"));
else
encode_int16 (insn->offset16.X_add_number, bytes + 2);
}
@ -941,8 +962,8 @@ encode_insn (struct bpf_insn *insn, char *bytes, int relaxed)
{
int64_t disp = insn->disp16.X_add_number;
if (!relaxed && signed_overflow (disp, 16))
as_bad (_("signed pc-relative offset out of range, shall fit in 16 bits"));
if (immediate_overflow (disp, 16))
as_bad (_("pc-relative offset out of range, shall fit in 16 bits"));
else
encode_int16 (insn->disp16.X_add_number, bytes + 2);
}
@ -1517,7 +1538,7 @@ md_assemble (char *str ATTRIBUTE_UNUSED)
break;
}
insn.has_disp16 = 1;
insn.is_relaxable = 1;
insn.is_relaxable = (insn.disp16.X_op != O_constant);
p += 4;
}
else if (strncmp (p, "%d32", 4) == 0)

View File

@ -844,7 +844,7 @@ struct pop_entry pop_table[] =
{
{ "hix", BFD_RELOC_SPARC_HIX22, F_POP_V9 },
{ "lox", BFD_RELOC_SPARC_LOX10, F_POP_V9 },
{ "hi", BFD_RELOC_HI22, F_POP_PCREL },
{ "hi"5, BFD_RELOC_HI22, F_POP_PCREL },
{ "lo", BFD_RELOC_LO10, F_POP_PCREL },
{ "pc22", BFD_RELOC_SPARC_PC22, F_POP_PCREL },
{ "pc10", BFD_RELOC_SPARC_PC10, F_POP_PCREL },

View File

@ -172,6 +172,14 @@ Signed 32-bit immediate.
Signed 64-bit immediate.
@end table
@noindent
Note that the assembler allows to express the value for an immediate
using any numerical literal whose two's complement encoding fits in
the immediate field. For example, @code{-2}, @code{0xfffffffe} and
@code{4294967294} all denote the same encoded 32-bit immediate, whose
value may be then interpreted by different instructions as either as a
negative or a positive number.
@subsection Arithmetic instructions
The destination register in these instructions act like an

View File

@ -1,3 +1,5 @@
.*: Assembler messages:
.*:2: Error: signed instruction operand out of range, shall fit in 32 bits
.*:4: Error: signed instruction operand out of range, shall fit in 32 bits
.*:1: Error: pc-relative offset out of range, shall fit in 16 bits
.*:2: Error: pc-relative offset out of range, shall fit in 16 bits
.*:3: Error: pc-relative offset out of range, shall fit in 16 bits
.*:4: Error: pc-relative offset out of range, shall fit in 16 bits

View File

@ -1,4 +1,4 @@
jeq %r1,%r2,2147483647
jeq %r1,%r2,2147483647 ; Overflows.
jlt %r3,%r4,2147483648 ; Overflows.
jge %r5,10,-2147483648
jge %r5,10,-2147483648 ; Overflows.
ja -2147483649 ; Overflows.

View File

@ -1,3 +1,3 @@
.*: Assembler messages:
.*:2: Error: signed pc-relative offset out of range, shall fit in 16 bits
.*:4: Error: signed pc-relative offset out of range, shall fit in 16 bits
.*:2: Error: pc-relative offset out of range, shall fit in 16 bits
.*:4: Error: pc-relative offset out of range, shall fit in 16 bits

View File

@ -1,4 +1,4 @@
ja 32767
jeq %r1,%r2,32768 ; Overflows
jeq %r1,%r2,65536 ; Overflows
jlt %r3,%r4,-32768
jge %r5,10,-32769 ; Overflows

View File

@ -1,3 +1,3 @@
.*: Assembler messages:
.*:2: Error: signed pc-relative offset out of range, shall fit in 32 bits
.*:4: Error: signed pc-relative offset out of range, shall fit in 32 bits
.*:2: Error: pc-relative offset out of range, shall fit in 32 bits
.*:4: Error: pc-relative offset out of range, shall fit in 32 bits

View File

@ -1,4 +1,4 @@
call -2147483648
call -2147483649 ; This overflows.
call 2147483647
call 2147483648 ; This overflows.
call 4294967295
call 4294967296 ; This overflows.

View File

@ -1,3 +1,3 @@
.*: Assembler messages:
.*:2: Error: signed immediate out of range, shall fit in 32 bits
.*:4: Error: signed immediate out of range, shall fit in 32 bits
.*:2: Error: immediate out of range, shall fit in 32 bits
.*:4: Error: immediate out of range, shall fit in 32 bits

View File

@ -1,4 +1,4 @@
add %r1, 2147483647
or %r2, 2147483648 ; This overflows.
xor %r3, -2147483648
sub %r4, -2147483649 ; This overflows.
or %r2, 4294967296 ; This overflows.
xor %r3, 4294967295
sub %r4, 4294967296 ; This overflows.

View File

@ -13,7 +13,5 @@ Disassembly of section .text:
10: 05 00 ff fd 00 00 00 00 ja -3
18: 05 00 00 00 00 00 00 00 ja 0
18: R_BPF_GNU_64_16 undefined
20: 06 00 00 00 ff ff 7f ff jal -32769
28: 06 00 00 00 00 00 80 00 jal 32768
30: 06 00 00 00 00 00 80 01 jal 32769
38: 06 00 00 00 00 00 80 01 jal 32769
20: 06 00 00 00 00 00 80 01 jal 32769
28: 06 00 00 00 00 00 80 01 jal 32769

View File

@ -13,7 +13,5 @@ Disassembly of section .text:
10: 05 00 fd ff 00 00 00 00 ja -3
18: 05 00 00 00 00 00 00 00 ja 0
18: R_BPF_GNU_64_16 undefined
20: 06 00 00 00 ff 7f ff ff jal -32769
28: 06 00 00 00 00 80 00 00 jal 32768
30: 06 00 00 00 01 80 00 00 jal 32769
38: 06 00 00 00 01 80 00 00 jal 32769
20: 06 00 00 00 01 80 00 00 jal 32769
28: 06 00 00 00 01 80 00 00 jal 32769

View File

@ -9,10 +9,6 @@
;; The following instruction has an undefined symbol as a
;; target. It is not to be relaxed.
ja undefined + 10
;; The following instructions are relaxed to JAL instructions
;; so they can fit their displacements.
ja -32769
ja 32768
;; The following instructions refer to a defined symbol that
;; is not on reach. They shall be relaxed to a JAL.
ja tail

View File

@ -11,15 +11,9 @@ Disassembly of section .text:
0: 1d 12 80 00 00 00 00 00 jeq %r1,%r2,-32768
8: ad 12 7f ff 00 00 00 00 jlt %r1,%r2,32767
10: bd 12 ff fd 00 00 00 00 jle %r1,%r2,-3
18: 3d 12 00 01 00 00 00 00 jge %r1,%r2,1
18: 1d 12 00 01 00 00 00 00 jeq %r1,%r2,1
20: 05 00 00 01 00 00 00 00 ja 1
28: 06 00 00 00 ff ff 7f ff jal -32769
28: 06 00 00 00 00 00 80 01 jal 32769
30: 2d 12 00 01 00 00 00 00 jgt %r1,%r2,1
38: 05 00 00 01 00 00 00 00 ja 1
40: 06 00 00 00 00 00 80 00 jal 32768
48: 1d 12 00 01 00 00 00 00 jeq %r1,%r2,1
50: 05 00 00 01 00 00 00 00 ja 1
58: 06 00 00 00 00 00 80 01 jal 32769
60: 2d 12 00 01 00 00 00 00 jgt %r1,%r2,1
68: 05 00 00 01 00 00 00 00 ja 1
70: 06 00 00 00 00 00 80 01 jal 32769
40: 06 00 00 00 00 00 80 01 jal 32769

View File

@ -11,15 +11,9 @@ Disassembly of section .text:
0: 1d 21 00 80 00 00 00 00 jeq %r1,%r2,-32768
8: ad 21 ff 7f 00 00 00 00 jlt %r1,%r2,32767
10: bd 21 fd ff 00 00 00 00 jle %r1,%r2,-3
18: 3d 21 01 00 00 00 00 00 jge %r1,%r2,1
18: 1d 21 01 00 00 00 00 00 jeq %r1,%r2,1
20: 05 00 01 00 00 00 00 00 ja 1
28: 06 00 00 00 ff 7f ff ff jal -32769
28: 06 00 00 00 01 80 00 00 jal 32769
30: 2d 21 01 00 00 00 00 00 jgt %r1,%r2,1
38: 05 00 01 00 00 00 00 00 ja 1
40: 06 00 00 00 00 80 00 00 jal 32768
48: 1d 21 01 00 00 00 00 00 jeq %r1,%r2,1
50: 05 00 01 00 00 00 00 00 ja 1
58: 06 00 00 00 01 80 00 00 jal 32769
60: 2d 21 01 00 00 00 00 00 jgt %r1,%r2,1
68: 05 00 01 00 00 00 00 00 ja 1
70: 06 00 00 00 01 80 00 00 jal 32769
40: 06 00 00 00 01 80 00 00 jal 32769

View File

@ -5,11 +5,6 @@
;; The following instruction refers to a defined symbol that
;; is on reach, so it should not be relaxed.
jle %r1, %r2, 1b
;; The following instructions are relaxed to sequences
;; involving unconditional jumps, so they can fi their
;; displacements.
jge %r1, %r2, -32769
jgt %r1, %r2, 32768
;; The following instructions refer to a defined symbol that
;; is not on reach. They shall be relaxed.
jeq %r1, %r2, tail

View File

@ -1,3 +1,3 @@
.*: Assembler messages:
.*:2: Error: signed pc-relative offset out of range, shall fit in 16 bits
.*:4: Error: signed pc-relative offset out of range, shall fit in 16 bits
.*:2: Error: pc-relative offset out of range, shall fit in 16 bits
.*:4: Error: pc-relative offset out of range, shall fit in 16 bits

View File

@ -1,4 +1,4 @@
ldxh %r2, [%r1 + 32767]
ldxw %r2, [%r1 + 32768] ; This overflows
ldxh %r2, [%r1 + 65535]
ldxw %r2, [%r1 + 65536] ; This overflows
stxw [%r2 - 32768], %r1
stxdw [%r2 - 32769], %r1 ; This overflows