]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
RISC-V: PR27566, consider ELF_MAXPAGESIZE/COMMONPAGESIZE for gp relaxations.
authorNelson Chu <nelson@rivosinc.com>
Fri, 12 May 2023 09:15:58 +0000 (17:15 +0800)
committerNelson Chu <nelson@rivosinc.com>
Fri, 6 Dec 2024 03:36:53 +0000 (11:36 +0800)
For default linker script, if a symbol's value outsides the bounds of the
defined section, then it may cross the data segment alignment, so we should
reserve more size about MAXPAGESIZE and COMMONPAGESIZE when doing gp
relaxations.  Otherwise we may meet the truncated errors since the data
segment alignment might move the section forward.

bfd/
PR 27566
* elfnn-riscv.c (_bfd_riscv_relax_lui): Consider MAXPAGESIZE and
COMMONPAGESIZE if the symbol's value outsides the bounds of the
defined section.
(_bfd_riscv_relax_pc): Likewise.
ld/
PR 27566
* testsuite/ld-riscv-elf/ld-riscv-elf.exp: Updated.
* testsuite/ld-riscv-elf/relax-data-segment-align*: New testcase
for pr27566.  Without this patch, the rv32 binutils will meet
truncated errors for this testcase.

bfd/elfnn-riscv.c
ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
ld/testsuite/ld-riscv-elf/relax-data-segment-align.d [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/relax-data-segment-align.s [new file with mode: 0644]

index 3aba9c85b0f3650fe1cd2b2f8aaec792aec2c388..8bbdd15d5522fc8505182cd3d12a02f786f2b996 100644 (file)
@@ -4755,6 +4755,9 @@ _bfd_riscv_relax_lui (bfd *abfd,
   bfd_vma gp = htab->params->relax_gp
               ? riscv_global_pointer_value (link_info)
               : 0;
+  bfd_vma data_segment_alignment = link_info->relro
+                                  ? ELF_MAXPAGESIZE + ELF_COMMONPAGESIZE
+                                  : ELF_MAXPAGESIZE;
   int use_rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC;
 
   BFD_ASSERT (rel->r_offset + 4 <= sec->size);
@@ -4779,6 +4782,16 @@ _bfd_riscv_relax_lui (bfd *abfd,
              htab->max_alignment_for_gp = max_alignment;
            }
        }
+
+      /* PR27566, for default linker script, if a symbol's value outsides the
+        bounds of the defined section, then it may cross the data segment
+        alignment, so we should reserve more size about MAXPAGESIZE and
+        COMMONPAGESIZE, since the data segment alignment might move the
+        section forward.  */
+      if (symval < sec_addr (sym_sec)
+         || symval > (sec_addr (sym_sec) + sym_sec->size))
+       max_alignment = data_segment_alignment > max_alignment
+                       ? data_segment_alignment : max_alignment;
     }
 
   /* Is the reference in range of x0 or gp?
@@ -4823,8 +4836,7 @@ _bfd_riscv_relax_lui (bfd *abfd,
       && ELFNN_R_TYPE (rel->r_info) == R_RISCV_HI20
       && VALID_CITYPE_LUI_IMM (RISCV_CONST_HIGH_PART (symval))
       && VALID_CITYPE_LUI_IMM (RISCV_CONST_HIGH_PART (symval)
-                           + (link_info->relro ? 2 * ELF_MAXPAGESIZE
-                              : ELF_MAXPAGESIZE)))
+                              + data_segment_alignment))
     {
       /* Replace LUI with C.LUI if legal (i.e., rd != x0 and rd != x2/sp).  */
       bfd_vma lui = bfd_getl32 (contents + rel->r_offset);
@@ -4969,6 +4981,9 @@ _bfd_riscv_relax_pc (bfd *abfd ATTRIBUTE_UNUSED,
   bfd_vma gp = htab->params->relax_gp
               ? riscv_global_pointer_value (link_info)
               : 0;
+  bfd_vma data_segment_alignment = link_info->relro
+                                  ? ELF_MAXPAGESIZE + ELF_COMMONPAGESIZE
+                                  : ELF_MAXPAGESIZE;
 
   BFD_ASSERT (rel->r_offset + 4 <= sec->size);
 
@@ -5043,6 +5058,16 @@ _bfd_riscv_relax_pc (bfd *abfd ATTRIBUTE_UNUSED,
              htab->max_alignment_for_gp = max_alignment;
            }
        }
+
+      /* PR27566, for default linker script, if a symbol's value outsides the
+        bounds of the defined section, then it may cross the data segment
+        alignment, so we should reserve more size about MAXPAGESIZE and
+        COMMONPAGESIZE, since the data segment alignment might move the
+        section forward.  */
+      if (symval < sec_addr (sym_sec)
+         || symval > (sec_addr (sym_sec) + sym_sec->size))
+       max_alignment = data_segment_alignment > max_alignment
+                       ? data_segment_alignment : max_alignment;
     }
 
   /* Is the reference in range of x0 or gp?
index 7b1b2aa285d3ac653e5b20e56c3ca935497b6852..5270addde26868c2644b23ce8530ca9987517ee2 100644 (file)
@@ -167,6 +167,7 @@ if [istarget "riscv*-*-*"] {
     run_dump_test "attr-merge-stack-align-failed"
     run_dump_test "attr-phdr"
     run_dump_test "relax-max-align-gp"
+    run_dump_test "relax-data-segment-align"
     run_dump_test "uleb128"
     run_dump_test "pr31179"
     run_dump_test "pr31179-r"
diff --git a/ld/testsuite/ld-riscv-elf/relax-data-segment-align.d b/ld/testsuite/ld-riscv-elf/relax-data-segment-align.d
new file mode 100644 (file)
index 0000000..22aeb4c
--- /dev/null
@@ -0,0 +1,8 @@
+#source: relax-data-segment-align.s
+#ld:
+#objdump: -d
+
+#failif
+#...
+.*gp.*
+#...
diff --git a/ld/testsuite/ld-riscv-elf/relax-data-segment-align.s b/ld/testsuite/ld-riscv-elf/relax-data-segment-align.s
new file mode 100644 (file)
index 0000000..9871892
--- /dev/null
@@ -0,0 +1,16 @@
+       .text
+       .globl _start
+_start:
+       .rept 6000
+       lla a0, symbol
+       .endr
+
+       .section .rodata
+       .set symbol, . + 4598
+       .fill 100, 4, 1
+
+       .data
+       .align 3
+       .rept 860
+       .long 0x1000
+       .endr