[PATCH] LoongArch: Fix the issue of excessive relocation generated by IE
Lulu Cai
cailulu@loongson.cn
Tue Jan 23 13:00:29 GMT 2024
Currently, whether GD and IE generate dynamic repositioning is
determined by SYMBOL_REFERENCES_LOCAL and bfd_link_executable.
This results in dynamic relocations still being generated in some
situations where dynamic relocations are not necessary (such as
the undefined weak symbol in static links).
We use RLARCH_TLS_GD_IE_NEED_DYN_RELOC macros to determine whether
GD/IE needs dynamic relocation. If GD/IE requires dynamic relocation,
set need_reloc/need_relocs to true and indx to be a dynamic index.
At the same time, some test cases were modified to use regular
expression matching instead of complete disassembly matching.
---
bfd/elfnn-loongarch.c | 154 +++++++++++---------
ld/testsuite/ld-loongarch-elf/desc-ie.d | 14 +-
ld/testsuite/ld-loongarch-elf/desc-le.d | 10 +-
ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d | 88 +++++------
4 files changed, 140 insertions(+), 126 deletions(-)
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index b2caa5fc3e1..b727c933e13 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -155,6 +155,27 @@ struct loongarch_elf_link_hash_table
((R_TYPE) == R_LARCH_TLS_IE_PC_HI20 \
|| (R_TYPE) == R_LARCH_TLS_IE_PC_LO12)
+/* If TLS GD/IE need dynamic relocations, INDX will be the dynamic indx,
+ and set NEED_RELOC to true used in allocate_dynrelocs and
+ loongarch_elf_relocate_section for TLS GD/IE. */
+#define LARCH_TLS_GD_IE_NEED_DYN_RELOC(INFO, DYN, H, INDX, NEED_RELOC) \
+ do \
+ { \
+ if ((H) != NULL \
+ && (H)->dynindx != -1 \
+ && WILL_CALL_FINISH_DYNAMIC_SYMBOL ((DYN), \
+ bfd_link_pic (INFO), (H))) \
+ (INDX) = (H)->dynindx; \
+ if (((H) == NULL \
+ || ELF_ST_VISIBILITY ((H)->other) == STV_DEFAULT \
+ || (H)->root.type != bfd_link_hash_undefweak) \
+ && (!bfd_link_executable (INFO) \
+ || (INDX) != 0)) \
+ (NEED_RELOC) = true; \
+ } \
+ while (0)
+
+
/* Generate a PLT header. */
static bool
@@ -1263,40 +1284,24 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
h->got.offset = s->size;
if (tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
{
+ int indx = 0;
+ bool need_reloc = false;
+ LARCH_TLS_GD_IE_NEED_DYN_RELOC (info, dyn, h, indx,
+ need_reloc);
/* TLS_GD needs two dynamic relocs and two GOT slots. */
if (tls_type & GOT_TLS_GD)
{
s->size += 2 * GOT_ENTRY_SIZE;
- if (bfd_link_executable (info))
- {
- /* Link exe and not defined local. */
- if (!SYMBOL_REFERENCES_LOCAL (info, h))
- htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
- }
- else
- {
- if (SYMBOL_REFERENCES_LOCAL (info, h))
- htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
- else
- htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
- }
+ if (need_reloc)
+ htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
}
/* TLS_IE needs one dynamic reloc and one GOT slot. */
if (tls_type & GOT_TLS_IE)
{
s->size += GOT_ENTRY_SIZE;
-
- if (bfd_link_executable (info))
- {
- /* Link exe and not defined local. */
- if (!SYMBOL_REFERENCES_LOCAL (info, h))
- htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
- }
- else
- {
- htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
- }
+ if (need_reloc)
+ htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
}
/* TLS_DESC needs one dynamic reloc and two GOT slot. */
@@ -2623,6 +2628,18 @@ loongarch_tls_relax (bfd *abfd, asection *sec, Elf_Internal_Rela *rel,
return false;
}
+#define TP_OFFSET 0
+
+/* Return the relocation value for a static TLS tp-relative relocation. */
+static bfd_vma
+tls_tpoff (struct bfd_link_info *info, bfd_vma addr)
+{
+ /* If tls_sec is NULL, we should have signalled an error already. */
+ if (elf_hash_table (info)->tls_sec == NULL)
+ return 0;
+ return addr - elf_hash_table (info)->tls_sec->vma - TP_OFFSET;
+}
+
static int
loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
@@ -3751,53 +3768,54 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
{
Elf_Internal_Rela rela;
asection *relgot = htab->elf.srelgot;
- bfd_vma tls_block_off = 0;
- if (SYMBOL_REFERENCES_LOCAL (info, h))
- {
- BFD_ASSERT (elf_hash_table (info)->tls_sec);
- tls_block_off = relocation
- - elf_hash_table (info)->tls_sec->vma;
- }
+ int indx = 0;
+ bool need_relocs = false;
+ LARCH_TLS_GD_IE_NEED_DYN_RELOC (info, is_dyn, h, indx, need_relocs);
if (tls_type & GOT_TLS_GD)
{
- rela.r_offset = sec_addr (got) + got_off;
- rela.r_addend = 0;
- if (SYMBOL_REFERENCES_LOCAL (info, h))
+ if (need_relocs)
{
- /* Local sym, used in exec, set module id 1. */
- if (bfd_link_executable (info))
- bfd_put_NN (output_bfd, 1, got->contents + got_off);
+ /* Dynamic resolved Module ID. */
+ rela.r_offset = sec_addr (got) + got_off;
+ rela.r_addend = 0;
+ rela.r_info = ELFNN_R_INFO (indx,R_LARCH_TLS_DTPMODNN);
+ bfd_put_NN (output_bfd, 0, got->contents + got_off);
+ loongarch_elf_append_rela (output_bfd, relgot, &rela);
+
+ if (indx == 0)
+ {
+ /* Local symbol, tp offset has been known. */
+ BFD_ASSERT (! unresolved_reloc);
+ bfd_put_NN (output_bfd, tls_tpoff (info, relocation),
+ (got->contents + got_off + GOT_ENTRY_SIZE));
+ }
else
{
- rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN);
+ /* Dynamic resolved block offset. */
+ bfd_put_NN (output_bfd, 0,
+ got->contents + got_off + GOT_ENTRY_SIZE);
+ rela.r_info = ELFNN_R_INFO (indx,
+ R_LARCH_TLS_DTPRELNN);
+ rela.r_offset += GOT_ENTRY_SIZE;
loongarch_elf_append_rela (output_bfd, relgot, &rela);
}
-
- bfd_put_NN (output_bfd, tls_block_off,
- got->contents + got_off + GOT_ENTRY_SIZE);
}
- /* Dynamic resolved. */
else
{
- /* Dynamic relocate module id. */
- rela.r_info = ELFNN_R_INFO (h->dynindx,
- R_LARCH_TLS_DTPMODNN);
- loongarch_elf_append_rela (output_bfd, relgot, &rela);
-
- /* Dynamic relocate offset of block. */
- rela.r_offset += GOT_ENTRY_SIZE;
- rela.r_info = ELFNN_R_INFO (h->dynindx,
- R_LARCH_TLS_DTPRELNN);
- loongarch_elf_append_rela (output_bfd, relgot, &rela);
+ /* In a static link or an executable link with the symbol
+ binding locally. Mark it as belonging to module 1. */
+ bfd_put_NN (output_bfd, 1, got->contents + got_off);
+ bfd_put_NN (output_bfd, tls_tpoff (info, relocation),
+ got->contents + got_off + GOT_ENTRY_SIZE);
}
}
if (tls_type & GOT_TLS_GDESC)
{
/* Unless it is a static link, DESC always emits a
dynamic relocation. */
- int indx = h && h->dynindx != -1 ? h->dynindx : 0;
+ indx = h && h->dynindx != -1 ? h->dynindx : 0;
rela.r_offset = sec_addr (got) + got_off + desc_off;
rela.r_addend = 0;
if (indx == 0)
@@ -3810,28 +3828,24 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
}
if (tls_type & GOT_TLS_IE)
{
- rela.r_offset = sec_addr (got) + got_off + ie_off;
- if (SYMBOL_REFERENCES_LOCAL (info, h))
+ if (need_relocs)
{
- /* Local sym, used in exec, set module id 1. */
- if (!bfd_link_executable (info))
- {
- rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
- rela.r_addend = tls_block_off;
- loongarch_elf_append_rela (output_bfd, relgot, &rela);
- }
+ bfd_put_NN (output_bfd, 0,
+ got->contents + got_off + ie_off);
+ rela.r_offset = sec_addr (got) + got_off + ie_off;
+ rela.r_addend = 0;
- bfd_put_NN (output_bfd, tls_block_off,
- got->contents + got_off + ie_off);
+ if (indx == 0)
+ rela.r_addend = tls_tpoff (info, relocation);
+ rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_TPRELNN);
+ loongarch_elf_append_rela (output_bfd, relgot, &rela);
}
- /* Dynamic resolved. */
else
{
- /* Dynamic relocate offset of block. */
- rela.r_info = ELFNN_R_INFO (h->dynindx,
- R_LARCH_TLS_TPRELNN);
- rela.r_addend = 0;
- loongarch_elf_append_rela (output_bfd, relgot, &rela);
+ /* In a static link or an executable link with the symbol
+ bindinglocally, compute offset directly. */
+ bfd_put_NN (output_bfd, tls_tpoff (info, relocation),
+ got->contents + got_off + ie_off);
}
}
}
diff --git a/ld/testsuite/ld-loongarch-elf/desc-ie.d b/ld/testsuite/ld-loongarch-elf/desc-ie.d
index 32e350507db..83ba5b5e9cb 100644
--- a/ld/testsuite/ld-loongarch-elf/desc-ie.d
+++ b/ld/testsuite/ld-loongarch-elf/desc-ie.d
@@ -7,10 +7,10 @@
Disassembly of section .text:
-0+230 <fn1>:
- 230: 1a000084 pcalau12i \$a0, 4
- 234: 28cd6084 ld.d \$a0, \$a0, 856
- 238: 03400000 nop.*
- 23c: 03400000 nop.*
- 240: 1a000084 pcalau12i \$a0, 4
- 244: 28cd6081 ld.d \$ra, \$a0, 856
+[0-9a-f]+ <fn1>:
+ +[0-9a-f]+: 1a000084 pcalau12i \$a0, .*
+ +[0-9a-f]+: 28cdc084 ld.d \$a0, \$a0, .*
+ +[0-9a-f]+: 03400000 nop.*
+ +[0-9a-f]+: 03400000 nop.*
+ +[0-9a-f]+: 1a000084 pcalau12i \$a0, .*
+ +[0-9a-f]+: 28cdc081 ld.d \$ra, \$a0, .*
diff --git a/ld/testsuite/ld-loongarch-elf/desc-le.d b/ld/testsuite/ld-loongarch-elf/desc-le.d
index b4ca9f82eb3..78202c1acde 100644
--- a/ld/testsuite/ld-loongarch-elf/desc-le.d
+++ b/ld/testsuite/ld-loongarch-elf/desc-le.d
@@ -8,8 +8,8 @@
Disassembly of section .text:
-0+1200000e8 <fn1>:
- 1200000e8: 14000004 lu12i.w \$a0, 0
- 1200000ec: 03800084 ori \$a0, \$a0, 0x0
- 1200000f0: 03400000 nop.*
- 1200000f4: 03400000 nop.*
+[0-9a-f]+ <fn1>:
+ +[0-9a-f]+: 14000004 lu12i.w \$a0, .*
+ +[0-9a-f]+: 03800084 ori \$a0, \$a0, .*
+ +[0-9a-f]+: 03400000 nop.*
+ +[0-9a-f]+: 03400000 nop.*
diff --git a/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d b/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
index 453902d1622..5cfccb84ccb 100644
--- a/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
+++ b/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
@@ -8,49 +8,49 @@
Disassembly of section .text:
-0+418 <fun_gl1>:
- 418: 180214c4 pcaddi \$a0, 4262
- 41c: 1a000084 pcalau12i \$a0, 4
- 420: 28db0084 ld.d \$a0, \$a0, 1728
- 424: 180212a4 pcaddi \$a0, 4245
- 428: 18021304 pcaddi \$a0, 4248
- 42c: 28c00081 ld.d \$ra, \$a0, 0
- 430: 4c000021 jirl \$ra, \$ra, 0
- 434: 1a000084 pcalau12i \$a0, 4
- 438: 28d9c084 ld.d \$a0, \$a0, 1648
- 43c: 03400000 nop.*
- 440: 03400000 nop.*
- 444: 1a000084 pcalau12i \$a0, 4
- 448: 28d9c084 ld.d \$a0, \$a0, 1648
- 44c: 18021264 pcaddi \$a0, 4243
- 450: 18021244 pcaddi \$a0, 4242
- 454: 28c00081 ld.d \$ra, \$a0, 0
- 458: 4c000021 jirl \$ra, \$ra, 0
- 45c: 1a000084 pcalau12i \$a0, 4
- 460: 28daa084 ld.d \$a0, \$a0, 1704
+[0-9a-f]+ <fun_gl1>:
+ +[0-9a-f]+: 180214c4 pcaddi \$a0, .*
+ +[0-9a-f]+: 1a000084 pcalau12i \$a0, .*
+ +[0-9a-f]+: 28dc2084 ld.d \$a0, \$a0, .*
+ +[0-9a-f]+: 180212a4 pcaddi \$a0, .*
+ +[0-9a-f]+: 18021304 pcaddi \$a0, .*
+ +[0-9a-f]+: 28c00081 ld.d \$ra, \$a0, .*
+ +[0-9a-f]+: 4c000021 jirl \$ra, \$ra, .*
+ +[0-9a-f]+: 1a000084 pcalau12i \$a0, .*
+ +[0-9a-f]+: 28dae084 ld.d \$a0, \$a0, .*
+ +[0-9a-f]+: 03400000 nop.*
+ +[0-9a-f]+: 03400000 nop.*
+ +[0-9a-f]+: 1a000084 pcalau12i \$a0, .*
+ +[0-9a-f]+: 28dae084 ld.d \$a0, \$a0, .*
+ +[0-9a-f]+: 18021264 pcaddi \$a0, .*
+ +[0-9a-f]+: 18021244 pcaddi \$a0, .*
+ +[0-9a-f]+: 28c00081 ld.d \$ra, \$a0, .*
+ +[0-9a-f]+: 4c000021 jirl \$ra, \$ra, .*
+ +[0-9a-f]+: 1a000084 pcalau12i \$a0, .*
+ +[0-9a-f]+: 28dbc084 ld.d \$a0, \$a0, .*
-0+464 <fun_lo>:
- 464: 1a000084 pcalau12i \$a0, 4
- 468: 28d86084 ld.d \$a0, \$a0, 1560
- 46c: 18020ce4 pcaddi \$a0, 4199
- 470: 18020e04 pcaddi \$a0, 4208
- 474: 28c00081 ld.d \$ra, \$a0, 0
- 478: 4c000021 jirl \$ra, \$ra, 0
- 47c: 18020d24 pcaddi \$a0, 4201
- 480: 1a000084 pcalau12i \$a0, 4
- 484: 28d90084 ld.d \$a0, \$a0, 1600
- 488: 03400000 nop.*
- 48c: 03400000 nop.*
- 490: 1a000084 pcalau12i \$a0, 4
- 494: 28d90084 ld.d \$a0, \$a0, 1600
- 498: 18020d84 pcaddi \$a0, 4204
- 49c: 28c00081 ld.d \$ra, \$a0, 0
- 4a0: 4c000021 jirl \$ra, \$ra, 0
- 4a4: 18020d24 pcaddi \$a0, 4201
- 4a8: 1a000084 pcalau12i \$a0, 4
- 4ac: 28d96084 ld.d \$a0, \$a0, 1624
+[0-9a-f]+ <fun_lo>:
+ +[0-9a-f]+: 1a000084 pcalau12i \$a0, .*
+ +[0-9a-f]+: 28d98084 ld.d \$a0, \$a0, .*
+ +[0-9a-f]+: 18020ce4 pcaddi \$a0, .*
+ +[0-9a-f]+: 18020e04 pcaddi \$a0, .*
+ +[0-9a-f]+: 28c00081 ld.d \$ra, \$a0, .*
+ +[0-9a-f]+: 4c000021 jirl \$ra, \$ra, .*
+ +[0-9a-f]+: 18020d24 pcaddi \$a0, .*
+ +[0-9a-f]+: 1a000084 pcalau12i \$a0, .*
+ +[0-9a-f]+: 28da2084 ld.d \$a0, \$a0, .*
+ +[0-9a-f]+: 03400000 nop.*
+ +[0-9a-f]+: 03400000 nop.*
+ +[0-9a-f]+: 1a000084 pcalau12i \$a0, .*
+ +[0-9a-f]+: 28da2084 ld.d \$a0, \$a0, .*
+ +[0-9a-f]+: 18020d84 pcaddi \$a0, .*
+ +[0-9a-f]+: 28c00081 ld.d \$ra, \$a0, .*
+ +[0-9a-f]+: 4c000021 jirl \$ra, \$ra, .*
+ +[0-9a-f]+: 18020d24 pcaddi \$a0, .*
+ +[0-9a-f]+: 1a000084 pcalau12i \$a0, .*
+ +[0-9a-f]+: 28da8084 ld.d \$a0, \$a0, .*
-0+4b0 <fun_external>:
- 4b0: 18020d84 pcaddi \$a0, 4204
- 4b4: 28c00081 ld.d \$ra, \$a0, 0
- 4b8: 4c000021 jirl \$ra, \$ra, 0
+[0-9a-f]+ <fun_external>:
+ +[0-9a-f]+: 18020d84 pcaddi \$a0, .*
+ +[0-9a-f]+: 28c00081 ld.d \$ra, \$a0, .*
+ +[0-9a-f]+: 4c000021 jirl \$ra, \$ra, .*
--
2.36.0
More information about the Binutils
mailing list