mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
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.
This commit is contained in:
parent
d3c2603167
commit
dffb4a0784
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user