From 792e4d23c9fccd0204c8c511368822913a5cdad0 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Fri, 11 Jul 2025 15:49:07 +0800 Subject: [PATCH] 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 Signed-off-by: WANG Xuerui --- bfd/elfnn-loongarch.c | 108 +++++++----------- .../ld-loongarch-elf/relax-after-alignment.d | 1 + 2 files changed, 45 insertions(+), 64 deletions(-) diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index c75f5206f2e..46fafb332de 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -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 (symval > pc) - pc -= (max_alignment > 4 ? max_alignment : 0); - else if (symval < pc) - pc += (max_alignment > 4 ? max_alignment : 0); - } + /* 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); 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 (symval > pc) - pc -= (max_alignment > 4 ? max_alignment : 0); - else if (symval < pc) - pc += (max_alignment > 4 ? max_alignment : 0); - } + /* 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); /* 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 (symval > pc) - pc -= (max_alignment > 4 ? max_alignment : 0); - else if (symval < pc) - pc += (max_alignment > 4 ? max_alignment : 0); - } + /* 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) || (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 (symval > pc) - pc -= (max_alignment > 4 ? max_alignment : 0); - else if (symval < pc) - pc += (max_alignment > 4 ? max_alignment : 0); - } + /* 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); const uint32_t pcaddi = LARCH_OP_PCADDI; diff --git a/ld/testsuite/ld-loongarch-elf/relax-after-alignment.d b/ld/testsuite/ld-loongarch-elf/relax-after-alignment.d index 844c518e9c7..08def250998 100644 --- a/ld/testsuite/ld-loongarch-elf/relax-after-alignment.d +++ b/ld/testsuite/ld-loongarch-elf/relax-after-alignment.d @@ -2,6 +2,7 @@ #as: #ld: --defsym _start=0 #objdump: -d --no-show-raw-insn +#xfail: *-*-* .*:\s+file format .* -- 2.47.2