[binutils-gdb] Not append rela for absolute symbol

liu & zhensong liuzhensong@sourceware.org
Sat Sep 7 02:07:54 GMT 2024


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

commit 9a33a0b9c65e587c3142600571f59efb25c973f9
Author: Xin Wang <yw987194828@gmail.com>
Date:   Fri Aug 16 11:28:10 2024 +0800

    Not append rela for absolute symbol
    
    LoongArch: Not append rela for absolute symbol
    
    Use la.global to get absolute symbol like la.abs.
    la.global put address of a global symbol into a got
    entry and append a rela for it, which will be used
    to relocate by dynamic linker. Dynamic linker should
    not relocate for got entry of absolute symbol as it
    stores symval not symbol's address.

Diff:
---
 bfd/elfnn-loongarch.c                              | 19 ++++++++++++++++++-
 ld/testsuite/ld-loongarch-elf/abs-global.out       |  1 +
 ld/testsuite/ld-loongarch-elf/abs-global.s         |  5 +++++
 ld/testsuite/ld-loongarch-elf/get_abs_global_sym.c |  7 +++++++
 ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp | 12 ++++++++++++
 5 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index b5b537b289c..5d7495c7fa5 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -4136,6 +4136,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		      if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
 							    bfd_link_pic (info),
 							    h)
+			  && !bfd_is_abs_section(h->root.u.def.section)
 			  && bfd_link_pic (info)
 			  && LARCH_REF_LOCAL (info, h)
 			  && !info->enable_dt_relr)
@@ -4158,7 +4159,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 			      && local_got_offsets[r_symndx] != MINUS_ONE);
 
 		  got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
-		  if ((local_got_offsets[r_symndx] & 1) == 0)
+		  if (sym->st_shndx != SHN_ABS
+		      && (local_got_offsets[r_symndx] & 1) == 0)
 		    {
 		      if (bfd_link_pic (info) && !info->enable_dt_relr)
 			{
@@ -5315,6 +5317,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
       bfd_vma symval;
       asection *sym_sec;
       bool local_got = false;
+      bool is_abs_symbol = false;
       Elf_Internal_Rela *rel = relocs + i;
       struct elf_link_hash_entry *h = NULL;
       unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
@@ -5496,7 +5499,21 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
 	  break;
 
 	case R_LARCH_GOT_PC_HI20:
+	  if (h)
+	    is_abs_symbol = bfd_is_abs_section(h->root.u.def.section);
+	  else
+	    {
+	      Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
+				    + ELFNN_R_SYM (rel->r_info);
+	      is_abs_symbol = sym->st_shndx == SHN_ABS;
+	    }
+	 /* If symval is in the range [-2^31, 2^31), we can relax the
+	    pair of instructions from pcalau12i/ld.d to lu12i.w/ori for
+	    abosulte symbol. This is not implemented yet, so we just
+	    remain the r_type which will be needed when relocate for
+	    absolute symbol. */
 	  if (local_got && 0 == info->relax_pass
+	      && !is_abs_symbol
 	      && (i + 4) <= sec->reloc_count)
 	    {
 	      if (loongarch_relax_pcala_ld (abfd, sec, rel))
diff --git a/ld/testsuite/ld-loongarch-elf/abs-global.out b/ld/testsuite/ld-loongarch-elf/abs-global.out
new file mode 100644
index 00000000000..3656652b938
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/abs-global.out
@@ -0,0 +1 @@
+abba
diff --git a/ld/testsuite/ld-loongarch-elf/abs-global.s b/ld/testsuite/ld-loongarch-elf/abs-global.s
new file mode 100644
index 00000000000..93a5da6dd22
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/abs-global.s
@@ -0,0 +1,5 @@
+.text
+.globl get_sym
+get_sym:
+ la.global $a0, sym
+ ret
diff --git a/ld/testsuite/ld-loongarch-elf/get_abs_global_sym.c b/ld/testsuite/ld-loongarch-elf/get_abs_global_sym.c
new file mode 100644
index 00000000000..29781ad7703
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/get_abs_global_sym.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+extern int get_sym();
+int main() {
+	printf("%x\n", get_sym());
+	return 0;
+}
diff --git a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
index 4328f6e941e..6bef97c260f 100644
--- a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
+++ b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
@@ -130,6 +130,18 @@ if [istarget "loongarch64-*-*"] {
 		"a.binary" \
 	   ] \
       ]
+
+
+  run_ld_link_exec_tests [list \
+	[list \
+	    "get global abs symbol test" \
+	    "-Wl,-z norelro -Wl,--defsym sym=0xabba" \
+	    "" \
+	    { abs-global.s get_abs_global_sym.c} \
+	    "abs-global" \
+	    "abs-global.out" \
+	] \
+    ]
 }
 
 if [istarget "loongarch64-*-*"] {


More information about the Binutils-cvs mailing list