aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormengqinggang <mengqinggang@loongson.cn>2024-10-10 16:23:30 +0800
committerliuzhensong <liuzhensong@loongson.cn>2024-10-15 14:26:17 +0800
commita104f0a3e62031d2a5aabfe9e82f55158647f444 (patch)
treed3bbe3b8cf84369c4ae025c380160e83f8d1359c
parent5c3d09c1855b948dd43b9f5f8b3d8aa254d75f43 (diff)
downloadbinutils-a104f0a3e62031d2a5aabfe9e82f55158647f444.zip
binutils-a104f0a3e62031d2a5aabfe9e82f55158647f444.tar.gz
binutils-a104f0a3e62031d2a5aabfe9e82f55158647f444.tar.bz2
LoongArch: Add more relaxation support for call36
Add relaxation support for call36 that jump to PLT entry. Add relaxation support for call36 with IFUNC symbol. Add relaxation support for call36 that jump to undefweak symbol. For undefweak symbol, it can always be relaxed if it have no PLT entry. Because we set the address of undefweak symbol without PLT entry to PC like relocate_section.
-rw-r--r--bfd/elfnn-loongarch.c21
-rw-r--r--ld/testsuite/ld-loongarch-elf/relax-call36-exe.s32
-rw-r--r--ld/testsuite/ld-loongarch-elf/relax-call36-so.s35
-rw-r--r--ld/testsuite/ld-loongarch-elf/relax.exp105
4 files changed, 190 insertions, 3 deletions
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index d683fd3..9c3cd67 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -5435,7 +5435,8 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
+ r_symndx;
- if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+ if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
+ && r_type != R_LARCH_CALL36)
continue;
/* Only TLS instruction sequences that are accompanied by
@@ -5468,8 +5469,8 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
}
else
{
- /* Disable the relaxation for ifunc. */
- if (h != NULL && h->type == STT_GNU_IFUNC)
+ if (h != NULL && h->type == STT_GNU_IFUNC
+ && r_type != R_LARCH_CALL36)
continue;
/* The GOT entry of tls symbols must in current execute file or
@@ -5486,6 +5487,20 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
&& GOT_TLS_GD_BOTH_P (tls_type))
symval += 2 * GOT_ENTRY_SIZE;
}
+ else if (h->plt.offset != MINUS_ONE)
+ {
+ sym_sec = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
+ symval = h->plt.offset;
+ }
+ /* Like loongarch_elf_relocate_section, set relocation(offset) to 0.
+ Undefweak for other relocations handing in the future. */
+ else if (h->root.type == bfd_link_hash_undefweak
+ && !h->root.linker_def
+ && r_type == R_LARCH_CALL36)
+ {
+ sym_sec = sec;
+ symval = rel->r_offset;
+ }
else if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& h->root.u.def.section != NULL
diff --git a/ld/testsuite/ld-loongarch-elf/relax-call36-exe.s b/ld/testsuite/ld-loongarch-elf/relax-call36-exe.s
new file mode 100644
index 0000000..26cff4d
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-call36-exe.s
@@ -0,0 +1,32 @@
+ldd: # local define default
+call36 ldd # ldd
+
+ldh: # local define hidden
+.hidden ldh
+call36 ldh # ldh
+
+gdd:
+.global gdd # global define default
+call36 gdd # gdd@plt
+
+gdh:
+.global gdh # global define hidden
+.hidden gdh
+call36 gdh # gdh
+
+wdd:
+.weak wdd # weak define default
+call36 wdd # wdd@plt
+
+.weak wud # weak undefine default
+call36 wud # wud@plt
+
+wdh:
+.weak wdh # weak define hidden
+.hidden wdh
+call36 wdh # wdh
+
+.weak wuh # weak undefine hidden
+.hidden wuh
+call36 wuh # wuh
+
diff --git a/ld/testsuite/ld-loongarch-elf/relax-call36-so.s b/ld/testsuite/ld-loongarch-elf/relax-call36-so.s
new file mode 100644
index 0000000..050273b
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-call36-so.s
@@ -0,0 +1,35 @@
+ldd: # local define default
+call36 ldd # ldd
+
+ldh: # local define hidden
+.hidden ldh
+call36 ldh # ldh
+
+gdd:
+.global gdd # global define default
+call36 gdd # gdd@plt
+
+.global gud # global undefine default
+call36 gud # gud@plt
+
+gdh:
+.global gdh # global define hidden
+.hidden gdh
+call36 gdh # gdh
+
+wdd:
+.weak wdd # weak define default
+call36 wdd # wdd@plt
+
+.weak wud # weak undefine default
+call36 wud # wud@plt
+
+wdh:
+.weak wdh # weak define hidden
+.hidden wdh
+call36 wdh # wdh
+
+.weak wuh # weak undefine hidden
+.hidden wuh
+call36 wuh # wuh
+
diff --git a/ld/testsuite/ld-loongarch-elf/relax.exp b/ld/testsuite/ld-loongarch-elf/relax.exp
index 4771f1e..aef7448 100644
--- a/ld/testsuite/ld-loongarch-elf/relax.exp
+++ b/ld/testsuite/ld-loongarch-elf/relax.exp
@@ -52,6 +52,111 @@ if [istarget loongarch64-*-*] {
run_partial_linking_align_test
run_ld_link_tests \
+ [list \
+ [list \
+ "loongarch relax call36 .so build" \
+ "-shared" "" \
+ "" \
+ {relax-call36-so.s} \
+ {} \
+ "relax-call36.so" \
+ ] \
+ ]
+
+ if [file exist "tmpdir/relax-call36.so"] {
+ set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-call36.so"]
+ if { [ regexp "pcaddu18i" $objdump_output] } {
+ fail "loongarch relax call36 so"
+ } {
+ pass "loongarch relax call36 so"
+ }
+ }
+
+ run_ld_link_tests \
+ [list \
+ [list \
+ "loongarch relax call36 dyn exe build" \
+ "-pie -e 0" "" \
+ "" \
+ {relax-call36-exe.s} \
+ {} \
+ "relax-call36-d.exe" \
+ ] \
+ ]
+
+ if [file exist "tmpdir/relax-call36-d.exe"] {
+ set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-call36-d.exe"]
+ if { [ regexp "pcaddu18i" $objdump_output] } {
+ fail "loongarch relax call36 dyn exe"
+ } {
+ pass "loongarch relax call36 dyn exe"
+ }
+ }
+
+ run_ld_link_tests \
+ [list \
+ [list \
+ "loongarch relax call36 dyn-pie exe build" \
+ "-pie -e 0" "" \
+ "" \
+ {relax-call36-exe.s} \
+ {} \
+ "relax-call36-dp.exe" \
+ ] \
+ ]
+
+ if [file exist "tmpdir/relax-call36-dp.exe"] {
+ set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-call36-dp.exe"]
+ if { [ regexp "pcaddu18i" $objdump_output] } {
+ fail "loongarch relax call36 dyn-pie exe"
+ } {
+ pass "loongarch relax call36 dyn-pie exe"
+ }
+ }
+
+ run_ld_link_tests \
+ [list \
+ [list \
+ "loongarch relax call36 static exe build" \
+ "-static -e 0" "" \
+ "" \
+ {relax-call36-exe.s} \
+ {} \
+ "relax-call36-s.exe" \
+ ] \
+ ]
+
+ if [file exist "tmpdir/relax-call36-s.exe"] {
+ set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-call36-s.exe"]
+ if { [ regexp "pcaddu18i" $objdump_output] } {
+ fail "loongarch relax call36 static exe"
+ } {
+ pass "loongarch relax call36 static exe"
+ }
+ }
+
+ run_ld_link_tests \
+ [list \
+ [list \
+ "loongarch relax call36 static-pie exe build" \
+ "-static -pie --no-dynamic-linker -e 0" "" \
+ "" \
+ {relax-call36-exe.s} \
+ {} \
+ "relax-call36-sp.exe" \
+ ] \
+ ]
+
+ if [file exist "tmpdir/relax-call36-sp.exe"] {
+ set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-call36-sp.exe"]
+ if { [ regexp "pcaddu18i" $objdump_output] } {
+ fail "loongarch relax call36 static-pie exe"
+ } {
+ pass "loongarch relax call36 static-pie exe"
+ }
+ }
+
+ run_ld_link_tests \
[list \
[list \
"loongarch relax ttext" \