LoongArch: Un-skip cross-segment alignment compensation during relax pass 2

It turned out wrong to skip compensating for segment alignment if the
current section is closed for deletion, as my recent system update with
binutils trunk revealed link failures of many high-profile packages such
as ffmpeg, numpy and wxGTK -- the dreaded "relocation truncated to fit"
errors regarding improperly produced R_LARCH_PCREL20_S2.

As it's near 2.45 branching time, revert the problematic change and
XFAIL the original test case for now.

Suggested-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: WANG Xuerui <git@xen0n.name>
This commit is contained in:
WANG Xuerui
2025-07-11 15:49:07 +08:00
committed by cailulu
parent 7ea90d9316
commit 792e4d23c9
2 changed files with 41 additions and 60 deletions

View File

@@ -5374,22 +5374,17 @@ loongarch_relax_pcala_addi (bfd *abfd, asection *sec, asection *sym_sec,
symval = sec_addr (sec)
+ loongarch_calc_relaxed_addr (info, symval - sec_addr (sec));
/* If pc and symbol not in the same segment, add/sub segment alignment if the
section has not undergone alignment processing because distances may grow
after alignment. */
if (!loongarch_sec_closed_for_deletion (sec))
{
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 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 (symval > pc)
pc -= (max_alignment > 4 ? max_alignment : 0);
else if (symval < pc)
pc += (max_alignment > 4 ? max_alignment : 0);
const uint32_t pcaddi = LARCH_OP_PCADDI;
@@ -5444,22 +5439,17 @@ loongarch_relax_call36 (bfd *abfd, asection *sec, asection *sym_sec,
symval = sec_addr (sec)
+ loongarch_calc_relaxed_addr (info, symval - sec_addr (sec));
/* If pc and symbol not in the same segment, add/sub segment alignment if the
section has not undergone alignment processing because distances may grow
after alignment. */
if (!loongarch_sec_closed_for_deletion (sec))
{
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 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 (symval > pc)
pc -= (max_alignment > 4 ? max_alignment : 0);
else if (symval < pc)
pc += (max_alignment > 4 ? max_alignment : 0);
/* Is pcalau12i + addi.d insns? */
if (!LARCH_INSN_JIRL (jirl)
@@ -5513,22 +5503,17 @@ loongarch_relax_pcala_ld (bfd *abfd, asection *sec,
symval = sec_addr (sec)
+ loongarch_calc_relaxed_addr (info, symval - sec_addr (sec));
/* If pc and symbol not in the same segment, add/sub segment alignment if the
section has not undergone alignment processing because distances may grow
after alignment. */
if (!loongarch_sec_closed_for_deletion (sec))
{
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 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 (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)
|| (LARCH_GET_RD (ld) != rd)
@@ -5651,22 +5636,17 @@ loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec,
symval = sec_addr (sec)
+ loongarch_calc_relaxed_addr (info, symval - sec_addr (sec));
/* If pc and symbol not in the same segment, add/sub segment alignment if the
section has not undergone alignment processing because distances may grow
after alignment. */
if (!loongarch_sec_closed_for_deletion (sec))
{
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 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 (symval > pc)
pc -= (max_alignment > 4 ? max_alignment : 0);
else if (symval < pc)
pc += (max_alignment > 4 ? max_alignment : 0);
const uint32_t pcaddi = LARCH_OP_PCADDI;

View File

@@ -2,6 +2,7 @@
#as:
#ld: --defsym _start=0
#objdump: -d --no-show-raw-insn
#xfail: *-*-*
.*:\s+file format .*