aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elfnn-loongarch.c19
-rw-r--r--ld/testsuite/ld-loongarch-elf/abs-global.out1
-rw-r--r--ld/testsuite/ld-loongarch-elf/abs-global.s5
-rw-r--r--ld/testsuite/ld-loongarch-elf/get_abs_global_sym.c7
-rw-r--r--ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp12
5 files changed, 43 insertions, 1 deletions
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index b5b537b..5d7495c 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 0000000..3656652
--- /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 0000000..93a5da6
--- /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 0000000..29781ad
--- /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 4328f6e..6bef97c2 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-*-*"] {