mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 10:03:47 +08:00
LoongArch: Do not relax pcalau12i+ld.d when there is overflow
There is no overflow check for the relaxation of pcalau12i+ld.d => pcalau12i+addi.d. For instruction sequences that can be relaxed, they are directly relaxed to pcalau12i+addi.d. However, when the relative distance between the symbol and the pc exceeds the 32-bit range, the symbol value cannot be obtained correctly. Adds an overflow check for the relaxation of pcalau12i+ld.d. If it is found that the relaxation will overflow, it will not be relaxed.
This commit is contained in:
parent
0073bda210
commit
77bcfb741c
@ -5099,12 +5099,12 @@ loongarch_relax_call36 (bfd *abfd, asection *sec, asection *sym_sec,
|
|||||||
/* Relax pcalau12i,ld.d => pcalau12i,addi.d. */
|
/* Relax pcalau12i,ld.d => pcalau12i,addi.d. */
|
||||||
static bool
|
static bool
|
||||||
loongarch_relax_pcala_ld (bfd *abfd, asection *sec,
|
loongarch_relax_pcala_ld (bfd *abfd, asection *sec,
|
||||||
asection *sym_sec ATTRIBUTE_UNUSED,
|
asection *sym_sec,
|
||||||
Elf_Internal_Rela *rel_hi,
|
Elf_Internal_Rela *rel_hi,
|
||||||
bfd_vma symval ATTRIBUTE_UNUSED,
|
bfd_vma symval,
|
||||||
struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
struct bfd_link_info *info,
|
||||||
bool *again ATTRIBUTE_UNUSED,
|
bool *again ATTRIBUTE_UNUSED,
|
||||||
bfd_vma max_alignment ATTRIBUTE_UNUSED)
|
bfd_vma max_alignment)
|
||||||
{
|
{
|
||||||
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
|
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
|
||||||
Elf_Internal_Rela *rel_lo = rel_hi + 2;
|
Elf_Internal_Rela *rel_lo = rel_hi + 2;
|
||||||
@ -5113,10 +5113,32 @@ loongarch_relax_pcala_ld (bfd *abfd, asection *sec,
|
|||||||
uint32_t rd = LARCH_GET_RD (pca);
|
uint32_t rd = LARCH_GET_RD (pca);
|
||||||
uint32_t addi_d = LARCH_OP_ADDI_D;
|
uint32_t addi_d = LARCH_OP_ADDI_D;
|
||||||
|
|
||||||
|
/* This section's output_offset need to subtract the bytes of instructions
|
||||||
|
relaxed by the previous sections, so it needs to be updated beforehand.
|
||||||
|
size_input_section already took care of updating it after relaxation,
|
||||||
|
so we additionally update once here. */
|
||||||
|
sec->output_offset = sec->output_section->size;
|
||||||
|
bfd_vma pc = sec_addr (sec) + rel_hi->r_offset;
|
||||||
|
|
||||||
|
/* If pc and symbol not in the same segment, add/sub segment alignment. */
|
||||||
|
if (!loongarch_two_sections_in_same_segment (info->output_bfd,
|
||||||
|
sec->output_section,
|
||||||
|
sym_sec->output_section))
|
||||||
|
max_alignment = info->maxpagesize > max_alignment ? info->maxpagesize
|
||||||
|
: max_alignment;
|
||||||
|
|
||||||
|
if (symval > pc)
|
||||||
|
pc -= (max_alignment > 4 ? max_alignment : 0);
|
||||||
|
else if (symval < pc)
|
||||||
|
pc += (max_alignment > 4 ? max_alignment : 0);
|
||||||
|
|
||||||
if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_GOT_PC_LO12)
|
if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_GOT_PC_LO12)
|
||||||
|| (LARCH_GET_RD (ld) != rd)
|
|| (LARCH_GET_RD (ld) != rd)
|
||||||
|| (LARCH_GET_RJ (ld) != rd)
|
|| (LARCH_GET_RJ (ld) != rd)
|
||||||
|| !LARCH_INSN_LD_D (ld))
|
|| !LARCH_INSN_LD_D (ld)
|
||||||
|
/* Within +-2G addressing range. */
|
||||||
|
|| (bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0x80000000
|
||||||
|
|| (bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x7fffffff)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
addi_d = addi_d | (rd << 5) | rd;
|
addi_d = addi_d | (rd << 5) | rd;
|
||||||
|
60
ld/testsuite/ld-loongarch-elf/check_got_relax.d
Normal file
60
ld/testsuite/ld-loongarch-elf/check_got_relax.d
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#ld: -T check_relax_got.ld
|
||||||
|
#objdump: -D
|
||||||
|
|
||||||
|
.*: file format .*
|
||||||
|
|
||||||
|
|
||||||
|
Disassembly of section .text:
|
||||||
|
|
||||||
|
0+10000 <_start>:
|
||||||
|
10000: 1a03fe04 pcalau12i \$a0, 8176
|
||||||
|
10004: 28c06084 ld.d \$a0, \$a0, 24
|
||||||
|
10008: 1a03fe04 pcalau12i \$a0, 8176
|
||||||
|
1000c: 28c08084 ld.d \$a0, \$a0, 32
|
||||||
|
10010: 1a03fe04 pcalau12i \$a0, 8176
|
||||||
|
10014: 28c04084 ld.d \$a0, \$a0, 16
|
||||||
|
|
||||||
|
0+10018 <sym_default_1>:
|
||||||
|
10018: 00000123 .word 0x00000123
|
||||||
|
|
||||||
|
0+1001c <sym_hidden_1>:
|
||||||
|
1001c: 00000123 .word 0x00000123
|
||||||
|
|
||||||
|
0+10020 <sym_protected_1>:
|
||||||
|
10020: 00000123 .word 0x00000123
|
||||||
|
|
||||||
|
Disassembly of section .got:
|
||||||
|
|
||||||
|
0+2000000 <_GLOBAL_OFFSET_TABLE_>:
|
||||||
|
...
|
||||||
|
2000008: 00010018 .word 0x00010018
|
||||||
|
200000c: 00000000 .word 0x00000000
|
||||||
|
2000010: 82000020 .word 0x82000020
|
||||||
|
2000014: 00000000 .word 0x00000000
|
||||||
|
2000018: 82000018 .word 0x82000018
|
||||||
|
200001c: 00000000 .word 0x00000000
|
||||||
|
2000020: 8200001c .word 0x8200001c
|
||||||
|
2000024: 00000000 .word 0x00000000
|
||||||
|
2000028: 0001001c .word 0x0001001c
|
||||||
|
200002c: 00000000 .word 0x00000000
|
||||||
|
2000030: 00010020 asrtle.d \$ra, \$zero
|
||||||
|
2000034: 00000000 .word 0x00000000
|
||||||
|
|
||||||
|
Disassembly of section .other:
|
||||||
|
|
||||||
|
0+82000000 <underflow>:
|
||||||
|
82000000: 1b000004 pcalau12i \$a0, -524288
|
||||||
|
82000004: 28c02084 ld.d \$a0, \$a0, 8
|
||||||
|
82000008: 1b000004 pcalau12i \$a0, -524288
|
||||||
|
8200000c: 28c0a084 ld.d \$a0, \$a0, 40
|
||||||
|
82000010: 1b000004 pcalau12i \$a0, -524288
|
||||||
|
82000014: 28c0c084 ld.d \$a0, \$a0, 48
|
||||||
|
|
||||||
|
0+82000018 <sym_default_2>:
|
||||||
|
82000018: 00000456 .word 0x00000456
|
||||||
|
|
||||||
|
0+8200001c <sym_hidden_2>:
|
||||||
|
8200001c: 00000456 .word 0x00000456
|
||||||
|
|
||||||
|
0+82000020 <sym_protected_2>:
|
||||||
|
82000020: 00000456 .word 0x00000456
|
43
ld/testsuite/ld-loongarch-elf/check_got_relax.s
Normal file
43
ld/testsuite/ld-loongarch-elf/check_got_relax.s
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
.text
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
|
||||||
|
# dot not relax when overflow
|
||||||
|
la.got $a0,sym_default_2
|
||||||
|
la.got $a0,sym_hidden_2
|
||||||
|
la.got $a0,sym_protected_2
|
||||||
|
|
||||||
|
sym_default_1:
|
||||||
|
.word 0x123
|
||||||
|
|
||||||
|
.global sym_hidden_1
|
||||||
|
.hidden sym_hidden_1
|
||||||
|
sym_hidden_1:
|
||||||
|
.word 0x123
|
||||||
|
|
||||||
|
.global sym_protected_1
|
||||||
|
.protected sym_protected_1
|
||||||
|
sym_protected_1:
|
||||||
|
.word 0x123
|
||||||
|
|
||||||
|
|
||||||
|
.section .other,"ax",@progbits
|
||||||
|
underflow:
|
||||||
|
# dot not relax when underflow
|
||||||
|
la.got $a0,sym_default_1
|
||||||
|
la.got $a0,sym_hidden_1
|
||||||
|
la.got $a0,sym_protected_1
|
||||||
|
|
||||||
|
.global sym_default_2
|
||||||
|
sym_default_2:
|
||||||
|
.word 0x456
|
||||||
|
|
||||||
|
.global sym_hidden_2
|
||||||
|
.hidden sym_hidden_2
|
||||||
|
sym_hidden_2:
|
||||||
|
.word 0x456
|
||||||
|
|
||||||
|
.global sym_protected_2
|
||||||
|
.protected sym_protected_2
|
||||||
|
sym_protected_2:
|
||||||
|
.word 0x456
|
25
ld/testsuite/ld-loongarch-elf/check_relax_got.ld
Normal file
25
ld/testsuite/ld-loongarch-elf/check_relax_got.ld
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
OUTPUT_ARCH(loongarch)
|
||||||
|
ENTRY(_start)
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
PROVIDE (__executable_start = 0x8000);
|
||||||
|
. = 0x10000;
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text)
|
||||||
|
} =0
|
||||||
|
. = 0x2000000;
|
||||||
|
.got :
|
||||||
|
{
|
||||||
|
*(.got.plt) *(.got)
|
||||||
|
}
|
||||||
|
. = 0x82000000;
|
||||||
|
.other :
|
||||||
|
{
|
||||||
|
*(.other)
|
||||||
|
}
|
||||||
|
/DISCARD/ :
|
||||||
|
{
|
||||||
|
*(*)
|
||||||
|
}
|
||||||
|
}
|
@ -47,6 +47,7 @@ if [istarget "loongarch64-*-*"] {
|
|||||||
run_dump_test "tls-le-relax"
|
run_dump_test "tls-le-relax"
|
||||||
run_dump_test "relax-medium-call"
|
run_dump_test "relax-medium-call"
|
||||||
run_dump_test "relax-medium-call-1"
|
run_dump_test "relax-medium-call-1"
|
||||||
|
run_dump_test "check_got_relax"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [istarget "loongarch32-*-*"] {
|
if [istarget "loongarch32-*-*"] {
|
||||||
|
Loading…
Reference in New Issue
Block a user