]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Not append rela for absolute symbol
authorXin Wang <yw987194828@gmail.com>
Fri, 16 Aug 2024 03:28:10 +0000 (11:28 +0800)
committerliuzhensong <liuzhensong@loongson.cn>
Sat, 7 Sep 2024 02:07:13 +0000 (10:07 +0800)
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.

bfd/elfnn-loongarch.c
ld/testsuite/ld-loongarch-elf/abs-global.out [new file with mode: 0644]
ld/testsuite/ld-loongarch-elf/abs-global.s [new file with mode: 0644]
ld/testsuite/ld-loongarch-elf/get_abs_global_sym.c [new file with mode: 0644]
ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp

index b5b537b289c5a06c2b7e723569df200b116bdd97..5d7495c7fa56f94df84643d28d6c7b27a3a0f056 100644 (file)
@@ -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 (file)
index 0000000..3656652
--- /dev/null
@@ -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 (file)
index 0000000..93a5da6
--- /dev/null
@@ -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 (file)
index 0000000..29781ad
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+extern int get_sym();
+int main() {
+       printf("%x\n", get_sym());
+       return 0;
+}
index 4328f6e941e58b49497d08f88c1c122df1f70508..6bef97c260f83d9774de783819532c82d0dff574 100644 (file)
@@ -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-*-*"] {