]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
bpf: fix calculation when deciding to relax branch
authorDavid Faust <david.faust@oracle.com>
Thu, 25 Apr 2024 18:40:31 +0000 (11:40 -0700)
committerDavid Faust <david.faust@oracle.com>
Thu, 25 Apr 2024 20:16:34 +0000 (13:16 -0700)
In certain cases we were calculating the jump displacement incorrectly
when deciding whether to relax a branch.  This meant for some branches,
such as a very long backwards conditional branch, relaxation was not
done when it should have been.  The result was to error later, because
the actual jump displacement was too large to fit in the original
instruction.

This patch fixes up the displacement calculation so that those branches
are correctly relaxed and no longer result in an error.  In addition, it
changes md_convert_frag to install fixups for the JAL instructions in
the resulting relaxations rather than encoding the displacement value
directly.

gas/
* config/tc-bpf.c (relaxed_branch_length): Correct displacement
calculation when relaxing.
(md_convert_frag): Likewise.  Install fixups for JAL
instructions resulting from relaxation.
* testsuite/gas/bpf/jump-relax-ja-be.d: Correct and expand test.
* testsuite/gas/bpf/jump-relax-ja.d: Likewise.
* testsuite/gas/bpf/jump-relax-ja.s: Likewise.
* testsuite/gas/bpf/jump-relax-jump-be.d: Likewise.
* testsuite/gas/bpf/jump-relax-jump.d: Likewise.
* testsuite/gas/bpf/jump-relax-jump.s: Likewise.

gas/config/tc-bpf.c
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

index dfa44ea194c12af88040886e28f84cf1fc893f3f..effb4838601ec0558edfa40c5d0494c0bb099483 100644 (file)
@@ -434,6 +434,7 @@ relaxed_branch_length (fragS *fragp, asection *sec, int update)
           && sec == S_GET_SEGMENT (fragp->fr_symbol))
         {
           offsetT val = S_GET_VALUE (fragp->fr_symbol) + fragp->fr_offset;
+          val -= fragp->fr_address + fragp->fr_fix;
 
           /* Convert to 64-bit words, minus one.  */
           val = (val - 8) / 8;
@@ -578,6 +579,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
            && sec == S_GET_SEGMENT (fragp->fr_symbol))
     {
       offsetT val = S_GET_VALUE (fragp->fr_symbol) + fragp->fr_offset;
+      val -= fragp->fr_address + fragp->fr_fix;
       /* Convert to 64-bit blocks minus one.  */
       disp_to_target = (val - 8) / 8;
       disp_is_known = 1;
@@ -626,15 +628,27 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
             {
               /* 16-bit disp is known and not in range.  Turn the JA
                  into a JAL with a 32-bit displacement.  */
-              char bytes[8];
+              char bytes[8] = {0};
 
               bytes[0] = ((BPF_CLASS_JMP32|BPF_CODE_JA|BPF_SRC_K) >> 56) & 0xff;
               bytes[1] = (word >> 48) & 0xff;
               bytes[2] = 0; /* disp16 high */
               bytes[3] = 0; /* disp16 lo */
-              encode_int32 ((int32_t) disp_to_target, bytes + 4);
-
               write_insn_bytes (buf, bytes);
+
+              /* Install fixup for the JAL.  */
+              reloc_howto_type *reloc_howto
+                = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_BPF_DISP32);
+              if (!reloc_howto)
+                abort();
+
+              fixp = fix_new_exp (fragp, buf - (bfd_byte *) fragp->fr_literal,
+                                  bfd_get_reloc_size (reloc_howto),
+                                  &exp,
+                                  reloc_howto->pc_relative,
+                                  BFD_RELOC_BPF_DISP32);
+              fixp->fx_file = fragp->fr_file;
+              fixp->fx_line = fragp->fr_line;
             }
         }
       else
@@ -731,8 +745,23 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
               bytes[1] = 0;
               bytes[2] = 0;
               bytes[3] = 0;
-              encode_int32 ((int32_t) disp_to_target, bytes + 4);
+              encode_int32 ((int32_t) 0, bytes + 4);
               write_insn_bytes (buf, bytes);
+
+              /* Install fixup for the JAL.  */
+              reloc_howto_type *reloc_howto
+                = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_BPF_DISP32);
+              if (!reloc_howto)
+                abort();
+
+              fixp = fix_new_exp (fragp, buf - (bfd_byte *) fragp->fr_literal,
+                                  bfd_get_reloc_size (reloc_howto),
+                                  &exp,
+                                  reloc_howto->pc_relative,
+                                  BFD_RELOC_BPF_DISP32);
+              fixp->fx_file = fragp->fr_file;
+              fixp->fx_line = fragp->fr_line;
+
               buf += 8;
             }
         }
index 5f07847e90c29f213cfb07dcdf5758fa80ae7319..e5ad30da8073bb6ecad308ab3c91b48c48275b60 100644 (file)
@@ -8,10 +8,14 @@
 Disassembly of section .text:
 
 0+ <.*>:
-   0:  05 00 80 00 00 00 00 00         ja -32768
-   8:  05 00 7f ff 00 00 00 00         ja 32767
-  10:  05 00 ff fd 00 00 00 00         ja -3
-  18:  05 00 00 00 00 00 00 00         ja 0
+       0:      05 00 80 00 00 00 00 00         ja -32768
+       8:      05 00 7f ff 00 00 00 00         ja 32767
+      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 00 00 80 01         jal 32769
-  28:  06 00 00 00 00 00 80 01         jal 32769
+      20:      06 00 00 00 00 00 80 00         jal 32768
+      28:      05 00 7f ff 00 00 00 00         ja 32767
+       ...
+
+0+40028 <tail>:
+   40028:      06 00 00 00 ff ff 7f fa         jal -32774
index ed3aa6bad4e7714e8da67af9bb93f7563d13bc22..1ac33f5d2f5da01bfb538e8eebe39cc8cabd2db0 100644 (file)
@@ -8,10 +8,14 @@
 Disassembly of section .text:
 
 0+ <.*>:
-   0:  05 00 00 80 00 00 00 00         ja -32768
-   8:  05 00 ff 7f 00 00 00 00         ja 32767
-  10:  05 00 fd ff 00 00 00 00         ja -3
-  18:  05 00 00 00 00 00 00 00         ja 0
+       0:      05 00 00 80 00 00 00 00         ja -32768
+       8:      05 00 ff 7f 00 00 00 00         ja 32767
+      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 01 80 00 00         jal 32769
-  28:  06 00 00 00 01 80 00 00         jal 32769
+      20:      06 00 00 00 00 80 00 00         jal 32768
+      28:      05 00 ff 7f 00 00 00 00         ja 32767
+       ...
+
+0+40028 <tail>:
+   40028:      06 00 00 00 fa 7f ff ff         jal -32774
index f164176bbd56e5c4d9eba98dd4dfd243f6cbcf82..61f2e61cb3cda12c22d63fab3e4478cef3758400 100644 (file)
@@ -4,13 +4,18 @@
 1:      ja -32768
         ja 32767
         /* The following instruction refers to a defined symbol that
-           is on reach, so it should not be relaxed.  */
+           is in reach, so it should not be relaxed.  */
         ja 1b
         /* The following instruction has an undefined symbol as a
            target.  It is not to be relaxed.  */
         ja undefined + 10
-        /* The following instructions refer to a defined symbol that
-           is not on reach.  They shall be relaxed to a JAL.  */
+        /* The following instruction refers to a defined symbol that
+           is not in reach, so it shall be relaxed to JAL.  */
         ja tail
-        tail = .text + 262160
+        /* Now the symbol is in reach, and the following instruction
+           shall not be relaxed.  */
         ja tail
+        .space 262136
+        tail = .
+        /* The jump back is too large and shall be relaxed.  */
+        ja 1b
index 0cacdb38fc90c748c48f4aa636e5604830ccedeb..5cf3bce2a2b4be29420d7e55319d0c5564b0b514 100644 (file)
@@ -8,12 +8,16 @@
 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:  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 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 01         jal 32769
+       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:      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 00 00 80 00         jal 32768
+      30:      2d 12 7f ff 00 00 00 00         jgt %r1,%r2,32767
+       ...
+
+0+40030 <tail>:
+   40030:      55 10 00 01 00 00 00 00         jne %r1,0,1
+   40038:      05 00 00 01 00 00 00 00         ja 1
+   40040:      06 00 00 00 ff ff 7f f7         jal -32777
index dd31ba5f4e4adc71561d6feac5c9d3ea5c17a156..4300bf3f59f654117f85b709079da193a6e2b7e7 100644 (file)
@@ -8,12 +8,16 @@
 Disassembly of section .text:
 
 0+ <.*>:
-   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:  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 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 01 80 00 00         jal 32769
+       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:      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 00 80 00 00         jal 32768
+      30:      2d 21 ff 7f 00 00 00 00         jgt %r1,%r2,32767
+       ...
+
+0+40030 <tail>:
+   40030:      55 01 01 00 00 00 00 00         jne %r1,0,1
+   40038:      05 00 01 00 00 00 00 00         ja 1
+   40040:      06 00 00 00 f7 7f ff ff         jal -32777
index 5ea61109bcaa15360230c3315c28484e7c720e84..6b23c56514a16c060b06bea2f8ea1e7334db2dee 100644 (file)
@@ -2,11 +2,13 @@
            fix in the jump 16-bit signed displacement operand.  */
 1:      jeq %r1, %r2, -32768
         jlt %r1, %r2, 32767
-        /* The following instruction refers to a defined symbol that
-           is on reach, so it should not be relaxed.  */
+        /* The following instructions refer to defined symbols that
+           are in reach, so they should not be relaxed.  */
         jle %r1, %r2, 1b
-        /* The following instructions refer to a defined symbol that
-           is not on reach.  They shall be relaxed.  */
         jeq %r1, %r2, tail
-        tail = .text + 262160
         jgt %r1, %r2, tail
+        /* The following instructions refers to defined symbols that
+           are not in reach, so they shall be relaxied.  */
+        .space 262136
+        tail = .
+        jne %r1, 0, 1b