public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb] bpf: fix calculation when deciding to relax branch
@ 2024-04-25 20:18 David Faust
  0 siblings, 0 replies; only message in thread
From: David Faust @ 2024-04-25 20:18 UTC (permalink / raw)
  To: binutils-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=dffb4a0784f401c2aa20446abb651a4e19f34a44

commit dffb4a0784f401c2aa20446abb651a4e19f34a44
Author: David Faust <david.faust@oracle.com>
Date:   Thu Apr 25 11:40:31 2024 -0700

    bpf: fix calculation when deciding to relax branch
    
    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.

Diff:
---
 gas/config/tc-bpf.c                        | 37 ++++++++++++++++++++++++++----
 gas/testsuite/gas/bpf/jump-relax-ja-be.d   | 16 ++++++++-----
 gas/testsuite/gas/bpf/jump-relax-ja.d      | 16 ++++++++-----
 gas/testsuite/gas/bpf/jump-relax-ja.s      | 13 +++++++----
 gas/testsuite/gas/bpf/jump-relax-jump-be.d | 22 ++++++++++--------
 gas/testsuite/gas/bpf/jump-relax-jump.d    | 22 ++++++++++--------
 gas/testsuite/gas/bpf/jump-relax-jump.s    | 12 ++++++----
 7 files changed, 95 insertions(+), 43 deletions(-)

diff --git a/gas/config/tc-bpf.c b/gas/config/tc-bpf.c
index dfa44ea194c..effb4838601 100644
--- a/gas/config/tc-bpf.c
+++ b/gas/config/tc-bpf.c
@@ -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;
             }
         }
diff --git a/gas/testsuite/gas/bpf/jump-relax-ja-be.d b/gas/testsuite/gas/bpf/jump-relax-ja-be.d
index 5f07847e90c..e5ad30da807 100644
--- a/gas/testsuite/gas/bpf/jump-relax-ja-be.d
+++ b/gas/testsuite/gas/bpf/jump-relax-ja-be.d
@@ -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
diff --git a/gas/testsuite/gas/bpf/jump-relax-ja.d b/gas/testsuite/gas/bpf/jump-relax-ja.d
index ed3aa6bad4e..1ac33f5d2f5 100644
--- a/gas/testsuite/gas/bpf/jump-relax-ja.d
+++ b/gas/testsuite/gas/bpf/jump-relax-ja.d
@@ -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
diff --git a/gas/testsuite/gas/bpf/jump-relax-ja.s b/gas/testsuite/gas/bpf/jump-relax-ja.s
index f164176bbd5..61f2e61cb3c 100644
--- a/gas/testsuite/gas/bpf/jump-relax-ja.s
+++ b/gas/testsuite/gas/bpf/jump-relax-ja.s
@@ -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
diff --git a/gas/testsuite/gas/bpf/jump-relax-jump-be.d b/gas/testsuite/gas/bpf/jump-relax-jump-be.d
index 0cacdb38fc9..5cf3bce2a2b 100644
--- a/gas/testsuite/gas/bpf/jump-relax-jump-be.d
+++ b/gas/testsuite/gas/bpf/jump-relax-jump-be.d
@@ -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
diff --git a/gas/testsuite/gas/bpf/jump-relax-jump.d b/gas/testsuite/gas/bpf/jump-relax-jump.d
index dd31ba5f4e4..4300bf3f59f 100644
--- a/gas/testsuite/gas/bpf/jump-relax-jump.d
+++ b/gas/testsuite/gas/bpf/jump-relax-jump.d
@@ -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
diff --git a/gas/testsuite/gas/bpf/jump-relax-jump.s b/gas/testsuite/gas/bpf/jump-relax-jump.s
index 5ea61109bca..6b23c56514a 100644
--- a/gas/testsuite/gas/bpf/jump-relax-jump.s
+++ b/gas/testsuite/gas/bpf/jump-relax-jump.s
@@ -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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-04-25 20:18 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-25 20:18 [binutils-gdb] bpf: fix calculation when deciding to relax branch David Faust

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).