bpf: gas: consolidate handling of immediate overflows
authorJose E. Marchesi <jose.marchesi@oracle.com>
Thu, 17 Aug 2023 07:38:37 +0000 (09:38 +0200)
committerJose E. Marchesi <jose.marchesi@oracle.com>
Thu, 17 Aug 2023 07:41:43 +0000 (09:41 +0200)
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.

20 files changed:
gas/ChangeLog
gas/config/tc-bpf.c
gas/config/tc-sparc.c
gas/doc/c-bpf.texi
gas/testsuite/gas/bpf/disp16-overflow-relax.l
gas/testsuite/gas/bpf/disp16-overflow-relax.s
gas/testsuite/gas/bpf/disp16-overflow.l
gas/testsuite/gas/bpf/disp16-overflow.s
gas/testsuite/gas/bpf/disp32-overflow.l
gas/testsuite/gas/bpf/disp32-overflow.s
gas/testsuite/gas/bpf/imm32-overflow.l
gas/testsuite/gas/bpf/imm32-overflow.s
gas/testsuite/gas/bpf/jump-relax-ja-be.d
gas/testsuite/gas/bpf/jump-relax-ja.d
gas/testsuite/gas/bpf/jump-relax-ja.s
gas/testsuite/gas/bpf/jump-relax-jump-be.d
gas/testsuite/gas/bpf/jump-relax-jump.d
gas/testsuite/gas/bpf/jump-relax-jump.s
gas/testsuite/gas/bpf/offset16-overflow.l
gas/testsuite/gas/bpf/offset16-overflow.s

index 26d7dc1623b33add58d21360ddf438472c653546..3339c4cadd3d95410961a18544aacc0f3d25b49a 100644 (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.
index b4566d89ddf8c5e15bf209bf55e4efedfc953ae7..cdde05c913981fce27aa3c423b4ac8b05943d118 100644 (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);
+    }
+}
+
 \f
 /* 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)
index c273bd75c08ece1c543a6ec3b66cfc16cbd853da..8c23b65ca8b8385fdbf0aea384cecba0f362e1c0 100644 (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 },
index 6b43c77d5a08d6af110e09a2a1b95a393ba31bf5..75372de4ef41ebd7dc51dce5d84fb45560fb7af9 100644 (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
index ca572cbd0ffb59bd56fb8667702b2df60e3abd5f..935a8abaed3b72f75f37c0f3bc1a671e275c4177 100644 (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
index 3953992ad0769cc43f5c26054a5900854efd1c4d..05d505caaae6fb695ddadad2468718920b6202d7 100644 (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.
index 6404b1b2076c7affaa33df17080942f066c7f1fc..1fd0f94d0e22377102b2cf183825e341800c6695 100644 (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
index ab66753af7d1fd20682c6e8276a54aa45432b8fb..4a8fd9fcf1c4001028343fc3d59872f8d89888cc 100644 (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
index 8a6b6479f07746dc5793f33e5606ce6e75861f14..40a20dd88fb5f92cce48d98b1f09ae4f11fecdc1 100644 (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
index 03a0d97e6c6715d8a5e05cea4d6063afc11a1de3..11128a20dff2f5c5e0af22142d70cc54f0e77619 100644 (file)
@@ -1,4 +1,4 @@
         call -2147483648
         call -2147483649        ; This overflows.
-        call 2147483647
-        call 2147483648         ; This overflows.
+        call 4294967295
+        call 4294967296         ; This overflows.
index f6691c49cd584cbfc246a1145a09d4957a5331a0..4e5ac5ae06f5510b40ac24a84562236436b0b542 100644 (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
index 5cb858cee05e90904aa24d4841f72754d51cd427..b2ab43d2e7a054d7159a664300b8c638986326ef 100644 (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.
index 08b85a97b457ae244fea82d8ad8b5dd8e6724696..5f07847e90c29f213cfb07dcdf5758fa80ae7319 100644 (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
index 6b50973915d977644e1a84f80968e581d4f47554..ed3aa6bad4e7714e8da67af9bb93f7563d13bc22 100644 (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
index 8be3d7a42880bdef01680d91730048e29a9d5b88..1faf67909eb99f9a54f44c13795d6e0cd1d627af 100644 (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
index 5626d568734786d348c635db15ea87bd68a02a8a..0cacdb38fc90c748c48f4aa636e5604830ccedeb 100644 (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
index cd46ea7024e91b18906c0d0a9b49ccd418a35a8b..dd31ba5f4e4adc71561d6feac5c9d3ea5c17a156 100644 (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
index dabbab84f7c316c1fe36d5429e93b59f91d2813f..3ee7c873320eab1f706698d446ab00c914379a47 100644 (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
index 6404b1b2076c7affaa33df17080942f066c7f1fc..1fd0f94d0e22377102b2cf183825e341800c6695 100644 (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
index da9f633a337e6b43d9994121fba58d96a728e2fc..ebd8e05c09e3ab4c82ce1970d9d15e3f69155dab 100644 (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