Browse Source

bpf: gas: add field overflow checking to the BPF assembler

This patch makes the BPF assembler to throughfully check for overflow
in immediates.  This includes relaxed instructions.

Tested in bpf-unknown-none.

gas/ChangeLog:

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

	* config/tc-bpf.c (signed_overflow): Copy function from
	tc-aarch64.c.
	(encode_insn): Check for overflow in constant immediates.
	(add_relaxed_insn): Pass relax argument to encode_insn.
	(add_fixed_insn): Likewise.
	* testsuite/gas/bpf/disp16-overflow.d: New file.
	* testsuite/gas/bpf/disp16-overflow.s: Likewise.
	* testsuite/gas/bpf/disp16-overflow.l: Likewise.
	* testsuite/gas/bpf/disp32-overflow.d: Likewise.
	* testsuite/gas/bpf/disp32-overflow.s: Likewise.
	* testsuite/gas/bpf/disp32-overflow.l: Likewise.
	* testsuite/gas/bpf/imm32-overflow.d: Likewise.
	* testsuite/gas/bpf/imm32-overflow.s: Likewise.
	* testsuite/gas/bpf/imm32-overflow.l: Likewise.
	* testsuite/gas/bpf/offset16-overflow.d: Likewise.
	* testsuite/gas/bpf/offset16-overflow.s: Likewise.
	* testsuite/gas/bpf/offset16-overflow.l: Likewise.
	* testsuite/gas/bpf/disp16-overflow-relax.d: Likewise.
	* testsuite/gas/bpf/disp16-overflow-relax.l: Likewise.
	* testsuite/gas/bpf/disp16-overflow-relax.s: Likewise.
	* testsuite/gas/bpf/jump-relax-jump-be.d: New file.
	* testsuite/gas/bpf/bpf.exp: Run new tests.
gdb-14-branch
Jose E. Marchesi 3 years ago
parent
commit
0346042938
  1. 25
      gas/ChangeLog
  2. 63
      gas/config/tc-bpf.c
  3. 7
      gas/testsuite/gas/bpf/bpf.exp
  4. 3
      gas/testsuite/gas/bpf/disp16-overflow-relax.d
  5. 3
      gas/testsuite/gas/bpf/disp16-overflow-relax.l
  6. 4
      gas/testsuite/gas/bpf/disp16-overflow-relax.s
  7. 3
      gas/testsuite/gas/bpf/disp16-overflow.d
  8. 3
      gas/testsuite/gas/bpf/disp16-overflow.l
  9. 4
      gas/testsuite/gas/bpf/disp16-overflow.s
  10. 3
      gas/testsuite/gas/bpf/disp32-overflow.d
  11. 3
      gas/testsuite/gas/bpf/disp32-overflow.l
  12. 4
      gas/testsuite/gas/bpf/disp32-overflow.s
  13. 3
      gas/testsuite/gas/bpf/imm32-overflow.d
  14. 3
      gas/testsuite/gas/bpf/imm32-overflow.l
  15. 4
      gas/testsuite/gas/bpf/imm32-overflow.s
  16. 25
      gas/testsuite/gas/bpf/jump-relax-jump-be.d
  17. 3
      gas/testsuite/gas/bpf/offset16-overflow.d
  18. 3
      gas/testsuite/gas/bpf/offset16-overflow.l
  19. 4
      gas/testsuite/gas/bpf/offset16-overflow.s

25
gas/ChangeLog

@ -1,3 +1,28 @@
2023-07-30 Jose E. Marchesi <jose.marchesi@oracle.com>
* config/tc-bpf.c (signed_overflow): Copy function from
tc-aarch64.c.
(encode_insn): Check for overflow in constant immediates.
(add_relaxed_insn): Pass relax argument to encode_insn.
(add_fixed_insn): Likewise.
* testsuite/gas/bpf/disp16-overflow.d: New file.
* testsuite/gas/bpf/disp16-overflow.s: Likewise.
* testsuite/gas/bpf/disp16-overflow.l: Likewise.
* testsuite/gas/bpf/disp32-overflow.d: Likewise.
* testsuite/gas/bpf/disp32-overflow.s: Likewise.
* testsuite/gas/bpf/disp32-overflow.l: Likewise.
* testsuite/gas/bpf/imm32-overflow.d: Likewise.
* testsuite/gas/bpf/imm32-overflow.s: Likewise.
* testsuite/gas/bpf/imm32-overflow.l: Likewise.
* testsuite/gas/bpf/offset16-overflow.d: Likewise.
* testsuite/gas/bpf/offset16-overflow.s: Likewise.
* testsuite/gas/bpf/offset16-overflow.l: Likewise.
* testsuite/gas/bpf/disp16-overflow-relax.d: Likewise.
* testsuite/gas/bpf/disp16-overflow-relax.l: Likewise.
* testsuite/gas/bpf/disp16-overflow-relax.s: Likewise.
* testsuite/gas/bpf/jump-relax-jump-be.d: New file.
* testsuite/gas/bpf/bpf.exp: Run new tests.
2023-07-28 Jose E. Marchesi <jose.marchesi@oracle.com>
PR gas/30690

63
gas/config/tc-bpf.c

@ -272,6 +272,20 @@ md_section_align (segT segment, valueT size)
return ((size + (1 << align) - 1) & -(1 << align));
}
/* Return non-zero if the indicated VALUE has overflowed the maximum
range expressible by an signed number with the indicated number of
BITS. */
static bool
signed_overflow (offsetT value, unsigned bits)
{
offsetT lim;
if (bits >= sizeof (offsetT) * 8)
return false;
lim = (offsetT) 1 << (bits - 1);
return (value < -lim || value >= lim);
}
/* Functions concerning relocs. */
@ -549,6 +563,11 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
disp_is_known = 1;
}
/* The displacement should fit in a signed 32-bit number. */
if (disp_is_known && signed_overflow (disp_to_target, 32))
as_bad_where (fragp->fr_file, fragp->fr_line,
_("signed instruction operand out of range, shall fit in 32 bits"));
/* Now relax particular jump instructions. */
if (code == BPF_CODE_JA)
{
@ -835,7 +854,7 @@ 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)
encode_insn (struct bpf_insn *insn, char *bytes, int relaxed)
{
uint8_t src, dst;
@ -889,16 +908,44 @@ encode_insn (struct bpf_insn *insn, char *bytes)
/* Now the immediates that are known to be constant. */
if (insn->has_imm32 && insn->imm32.X_op == O_constant)
encode_int32 (insn->imm32.X_add_number, bytes + 4);
{
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"));
else
encode_int32 (insn->imm32.X_add_number, bytes + 4);
}
if (insn->has_disp32 && insn->disp32.X_op == O_constant)
encode_int32 (insn->disp32.X_add_number, bytes + 4);
{
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"));
else
encode_int32 (insn->disp32.X_add_number, bytes + 4);
}
if (insn->has_offset16 && insn->offset16.X_op == O_constant)
encode_int16 (insn->offset16.X_add_number, bytes + 2);
{
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"));
else
encode_int16 (insn->offset16.X_add_number, bytes + 2);
}
if (insn->has_disp16 && insn->disp16.X_op == O_constant)
encode_int16 (insn->disp16.X_add_number, bytes + 2);
{
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"));
else
encode_int16 (insn->disp16.X_add_number, bytes + 2);
}
if (insn->has_imm64 && insn->imm64.X_op == O_constant)
{
@ -1105,7 +1152,7 @@ add_fixed_insn (struct bpf_insn *insn)
/* First encode the known parts of the instruction, including
opcodes and constant immediates, and write them to the frag. */
encode_insn (insn, bytes);
encode_insn (insn, bytes, 0 /* relax */);
for (i = 0; i < insn->size; ++i)
md_number_to_chars (this_frag + i, (valueT) bytes[i], 1);
@ -1136,7 +1183,7 @@ add_relaxed_insn (struct bpf_insn *insn, expressionS *exp)
/* First encode the known parts of the instruction, including
opcodes and constant immediates, and write them to the frag. */
encode_insn (insn, bytes);
encode_insn (insn, bytes, 1 /* relax */);
for (i = 0; i < insn->size; ++i)
md_number_to_chars (this_frag + i, (valueT) bytes[i], 1);
@ -1555,7 +1602,7 @@ md_assemble (char *str ATTRIBUTE_UNUSED)
#undef PARSE_ERROR
/* Generate the frags and fixups for the parsed instruction. */
if (do_relax && insn.is_relaxable)
if (do_relax && isa_spec >= BPF_V4 && insn.is_relaxable)
{
expressionS *relaxable_exp = NULL;

7
gas/testsuite/gas/bpf/bpf.exp

@ -65,4 +65,11 @@ if {[istarget bpf*-*-*]} {
run_dump_test jump-relax-ja-be
run_dump_test jump-relax-jump-be
# Overflow tests
run_dump_test offset16-overflow
run_dump_test disp16-overflow
run_dump_test disp16-overflow-relax
run_dump_test disp32-overflow
run_dump_test imm32-overflow
}

3
gas/testsuite/gas/bpf/disp16-overflow-relax.d

@ -0,0 +1,3 @@
#as: -EL -misa-spec=v4
#source: disp16-overflow-relax.s
#error_output: disp16-overflow-relax.l

3
gas/testsuite/gas/bpf/disp16-overflow-relax.l

@ -0,0 +1,3 @@
.*: 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

4
gas/testsuite/gas/bpf/disp16-overflow-relax.s

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

3
gas/testsuite/gas/bpf/disp16-overflow.d

@ -0,0 +1,3 @@
#as: -EL -mno-relax
#source: disp16-overflow.s
#error_output: disp16-overflow.l

3
gas/testsuite/gas/bpf/disp16-overflow.l

@ -0,0 +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

4
gas/testsuite/gas/bpf/disp16-overflow.s

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

3
gas/testsuite/gas/bpf/disp32-overflow.d

@ -0,0 +1,3 @@
#as: -EL
#source: disp32-overflow.s
#error_output: disp32-overflow.l

3
gas/testsuite/gas/bpf/disp32-overflow.l

@ -0,0 +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

4
gas/testsuite/gas/bpf/disp32-overflow.s

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

3
gas/testsuite/gas/bpf/imm32-overflow.d

@ -0,0 +1,3 @@
#as: -EL
#source: imm32-overflow.s
#error_output: imm32-overflow.l

3
gas/testsuite/gas/bpf/imm32-overflow.l

@ -0,0 +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

4
gas/testsuite/gas/bpf/imm32-overflow.s

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

25
gas/testsuite/gas/bpf/jump-relax-jump-be.d

@ -0,0 +1,25 @@
#as: -EB -mdialect=normal
#objdump: -dr -M dec
#source: jump-relax-jump.s
#name: Relaxation of conditional branch instructions, big-endian
.*: +file format .*bpf.*
Disassembly of section .text:
0+ <.*>:
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
20: 05 00 00 01 00 00 00 00 ja 1
28: 06 00 00 00 ff ff 7f ff 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

3
gas/testsuite/gas/bpf/offset16-overflow.d

@ -0,0 +1,3 @@
#as: -EL
#source: offset16-overflow.s
#error_output: offset16-overflow.l

3
gas/testsuite/gas/bpf/offset16-overflow.l

@ -0,0 +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

4
gas/testsuite/gas/bpf/offset16-overflow.s

@ -0,0 +1,4 @@
ldxh %r2, [%r1 + 32767]
ldxw %r2, [%r1 + 32768] ; This overflows
stxw [%r2 - 32768], %r1
stxdw [%r2 - 32769], %r1 ; This overflows
Loading…
Cancel
Save