[binutils-gdb] RISC-V: PR27566, consider ELF_MAXPAGESIZE/COMMONPAGESIZE for gp relaxations.

Nelson Chu nelsonc1225@sourceware.org
Fri Dec 6 03:48:24 GMT 2024


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6f8e75592ceb1e667fb50e466734caf6d11203ac

commit 6f8e75592ceb1e667fb50e466734caf6d11203ac
Author: Nelson Chu <nelson@rivosinc.com>
Date:   Fri May 12 17:15:58 2023 +0800

    RISC-V: PR27566, consider ELF_MAXPAGESIZE/COMMONPAGESIZE for gp relaxations.
    
    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.

Diff:
---
 bfd/elfnn-riscv.c                                  | 29 ++++++++++++++++++++--
 ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp         |  1 +
 .../ld-riscv-elf/relax-data-segment-align.d        |  8 ++++++
 .../ld-riscv-elf/relax-data-segment-align.s        | 16 ++++++++++++
 4 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 3aba9c85b0f..8bbdd15d552 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -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?
diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
index 7b1b2aa285d..5270addde26 100644
--- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
+++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
@@ -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
index 00000000000..22aeb4c3f90
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relax-data-segment-align.d
@@ -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
index 00000000000..98718922fb5
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/relax-data-segment-align.s
@@ -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


More information about the Binutils-cvs mailing list