483 lines
18 KiB
Diff
483 lines
18 KiB
Diff
From 4c19c0fd7815a9acabdca9954028f772da1d985e Mon Sep 17 00:00:00 2001
|
|
From: mengqinggang <mengqinggang@loongson.cn>
|
|
Date: Thu, 10 Oct 2024 16:20:52 +0800
|
|
Subject: [PATCH 116/123] LoongArch: Optimize the relaxation process
|
|
|
|
The symbol value is only calculated when the relocation can be relaxed.
|
|
---
|
|
bfd/elfnn-loongarch.c | 281 +++++++++++++++++++++---------------------
|
|
1 file changed, 139 insertions(+), 142 deletions(-)
|
|
|
|
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
|
|
index b6d7d1e8..70522fae 100644
|
|
--- a/bfd/elfnn-loongarch.c
|
|
+++ b/bfd/elfnn-loongarch.c
|
|
@@ -4072,7 +4072,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
|
|
/* For 2G jump, generate pcalau12i, jirl. */
|
|
/* If use jirl, turns to R_LARCH_B16. */
|
|
uint32_t insn = bfd_get (32, input_bfd, contents + rel->r_offset);
|
|
- if (LARCH_INSN_JIRL(insn))
|
|
+ if (LARCH_INSN_JIRL (insn))
|
|
{
|
|
relocation &= 0xfff;
|
|
/* Signed extend. */
|
|
@@ -4852,9 +4852,11 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec,
|
|
*/
|
|
static bool
|
|
loongarch_relax_tls_le (bfd *abfd, asection *sec,
|
|
- Elf_Internal_Rela *rel,
|
|
+ asection *sym_sec ATTRIBUTE_UNUSED,
|
|
+ Elf_Internal_Rela *rel, bfd_vma symval,
|
|
struct bfd_link_info *link_info,
|
|
- bfd_vma symval)
|
|
+ bool *agin ATTRIBUTE_UNUSED,
|
|
+ bfd_vma max_alignment ATTRIBUTE_UNUSED)
|
|
{
|
|
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
|
|
uint32_t insn = bfd_get (32, abfd, contents + rel->r_offset);
|
|
@@ -4862,7 +4864,7 @@ loongarch_relax_tls_le (bfd *abfd, asection *sec,
|
|
symval = symval - elf_hash_table (link_info)->tls_sec->vma;
|
|
/* The old LE instruction sequence can be relaxed when the symbol offset
|
|
is smaller than the 12-bit range. */
|
|
- if (ELFNN_R_TYPE ((rel + 1)->r_info) == R_LARCH_RELAX && (symval <= 0xfff))
|
|
+ if (symval <= 0xfff)
|
|
{
|
|
switch (ELFNN_R_TYPE (rel->r_info))
|
|
{
|
|
@@ -4975,9 +4977,6 @@ loongarch_relax_pcala_addi (bfd *abfd, asection *sec, asection *sym_sec,
|
|
|
|
/* Is pcalau12i + addi.d insns? */
|
|
if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_PCALA_LO12)
|
|
- || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX)
|
|
- || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX)
|
|
- || (rel_hi->r_offset + 4 != rel_lo->r_offset)
|
|
|| !LARCH_INSN_ADDI_D(add)
|
|
/* Is pcalau12i $rd + addi.d $rd,$rd? */
|
|
|| (LARCH_GET_RD(add) != rd)
|
|
@@ -5035,10 +5034,8 @@ loongarch_relax_call36 (bfd *abfd, asection *sec, asection *sym_sec,
|
|
else if (symval < pc)
|
|
pc += (max_alignment > 4 ? max_alignment : 0);
|
|
|
|
-
|
|
/* Is pcalau12i + addi.d insns? */
|
|
- if ((ELFNN_R_TYPE ((rel + 1)->r_info) != R_LARCH_RELAX)
|
|
- || !LARCH_INSN_JIRL(jirl)
|
|
+ if (!LARCH_INSN_JIRL (jirl)
|
|
|| ((bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0xf8000000)
|
|
|| ((bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x7fffffc))
|
|
return false;
|
|
@@ -5064,7 +5061,12 @@ loongarch_relax_call36 (bfd *abfd, asection *sec, asection *sym_sec,
|
|
/* Relax pcalau12i,ld.d => pcalau12i,addi.d. */
|
|
static bool
|
|
loongarch_relax_pcala_ld (bfd *abfd, asection *sec,
|
|
- Elf_Internal_Rela *rel_hi)
|
|
+ asection *sym_sec ATTRIBUTE_UNUSED,
|
|
+ Elf_Internal_Rela *rel_hi,
|
|
+ bfd_vma symval ATTRIBUTE_UNUSED,
|
|
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
|
+ bool *again ATTRIBUTE_UNUSED,
|
|
+ bfd_vma max_alignment ATTRIBUTE_UNUSED)
|
|
{
|
|
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
|
|
Elf_Internal_Rela *rel_lo = rel_hi + 2;
|
|
@@ -5074,9 +5076,6 @@ loongarch_relax_pcala_ld (bfd *abfd, asection *sec,
|
|
uint32_t addi_d = LARCH_OP_ADDI_D;
|
|
|
|
if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_GOT_PC_LO12)
|
|
- || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX)
|
|
- || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX)
|
|
- || (rel_hi->r_offset + 4 != rel_lo->r_offset)
|
|
|| (LARCH_GET_RD(ld) != rd)
|
|
|| (LARCH_GET_RJ(ld) != rd)
|
|
|| !LARCH_INSN_LD_D(ld))
|
|
@@ -5106,11 +5105,12 @@ bfd_elfNN_loongarch_set_data_segment_info (struct bfd_link_info *info,
|
|
/* Implement R_LARCH_ALIGN by deleting excess alignment NOPs.
|
|
Once we've handled an R_LARCH_ALIGN, we can't relax anything else. */
|
|
static bool
|
|
-loongarch_relax_align (bfd *abfd, asection *sec,
|
|
- asection *sym_sec,
|
|
- struct bfd_link_info *link_info,
|
|
+loongarch_relax_align (bfd *abfd, asection *sec, asection *sym_sec,
|
|
Elf_Internal_Rela *rel,
|
|
- bfd_vma symval)
|
|
+ bfd_vma symval ATTRIBUTE_UNUSED,
|
|
+ struct bfd_link_info *link_info,
|
|
+ bool *again ATTRIBUTE_UNUSED,
|
|
+ bfd_vma max_alignment ATTRIBUTE_UNUSED)
|
|
{
|
|
bfd_vma addend, max = 0, alignment = 1;
|
|
|
|
@@ -5198,9 +5198,6 @@ loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec,
|
|
/* Is pcalau12i + addi.d insns? */
|
|
if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_GOT_PC_LO12
|
|
&& ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_TLS_DESC_PC_LO12)
|
|
- || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX)
|
|
- || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX)
|
|
- || (rel_hi->r_offset + 4 != rel_lo->r_offset)
|
|
|| !LARCH_INSN_ADDI_D(add)
|
|
/* Is pcalau12i $rd + addi.d $rd,$rd? */
|
|
|| (LARCH_GET_RD(add) != rd)
|
|
@@ -5257,12 +5254,18 @@ loongarch_get_max_alignment (asection *sec)
|
|
return (bfd_vma) 1 << max_alignment_power;
|
|
}
|
|
|
|
+typedef bool (*relax_func_t) (bfd *, asection *, asection *,
|
|
+ Elf_Internal_Rela *, bfd_vma,
|
|
+ struct bfd_link_info *, bool *,
|
|
+ bfd_vma);
|
|
+
|
|
static bool
|
|
loongarch_elf_relax_section (bfd *abfd, asection *sec,
|
|
struct bfd_link_info *info,
|
|
bool *again)
|
|
{
|
|
*again = false;
|
|
+
|
|
if (!is_elf_hash_table (info->hash)
|
|
|| elf_hash_table_id (elf_hash_table (info)) != LARCH_ELF_DATA)
|
|
return true;
|
|
@@ -5277,13 +5280,13 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
|
|
|
|
if (bfd_link_relocatable (info)
|
|
|| sec->sec_flg0
|
|
- || (sec->flags & SEC_RELOC) == 0
|
|
|| sec->reloc_count == 0
|
|
+ || (sec->flags & SEC_RELOC) == 0
|
|
+ || (sec->flags & SEC_HAS_CONTENTS) == 0
|
|
+ /* The exp_seg_relro_adjust is enum phase_enum (0x4). */
|
|
+ || *(htab->data_segment_phase) == 4
|
|
|| (info->disable_target_specific_optimizations
|
|
- && info->relax_pass == 0)
|
|
- /* The exp_seg_relro_adjust is enum phase_enum (0x4),
|
|
- and defined in ld/ldexp.h. */
|
|
- || *(htab->data_segment_phase) == 4)
|
|
+ && info->relax_pass == 0))
|
|
return true;
|
|
|
|
struct bfd_elf_section_data *data = elf_section_data (sec);
|
|
@@ -5293,11 +5296,14 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
|
|
else if (!(relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
|
|
info->keep_memory)))
|
|
return true;
|
|
+ data->relocs = relocs;
|
|
|
|
+ /* Read this BFD's contents if we haven't done so already. */
|
|
if (!data->this_hdr.contents
|
|
&& !bfd_malloc_and_get_section (abfd, sec, &data->this_hdr.contents))
|
|
return true;
|
|
|
|
+ /* Read this BFD's symbols if we haven't done so already. */
|
|
Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd);
|
|
if (symtab_hdr->sh_info != 0
|
|
&& !symtab_hdr->contents
|
|
@@ -5307,8 +5313,6 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
|
|
0, NULL, NULL, NULL)))
|
|
return true;
|
|
|
|
- data->relocs = relocs;
|
|
-
|
|
/* Estimate the maximum alignment for all output sections once time
|
|
should be enough. */
|
|
bfd_vma max_alignment = htab->max_alignment;
|
|
@@ -5330,6 +5334,93 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
|
|
unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
|
|
unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
|
|
|
|
+ if (r_symndx >= symtab_hdr->sh_info)
|
|
+ {
|
|
+ h = elf_sym_hashes (abfd)[r_symndx - symtab_hdr->sh_info];
|
|
+ while (h->root.type == bfd_link_hash_indirect
|
|
+ || h->root.type == bfd_link_hash_warning)
|
|
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
|
+ }
|
|
+
|
|
+ /* If the conditions for tls type transition are met, type
|
|
+ transition is performed instead of relax.
|
|
+ During the transition from DESC->IE/LE, there are 2 situations
|
|
+ depending on the different configurations of the relax/norelax
|
|
+ option.
|
|
+ If the -relax option is used, the extra nops will be removed,
|
|
+ and this transition is performed in pass 0.
|
|
+ If the --no-relax option is used, nop will be retained, and
|
|
+ this transition is performed in pass 1. */
|
|
+ if (IS_LOONGARCH_TLS_TRANS_RELOC (r_type)
|
|
+ && (i + 1 != sec->reloc_count)
|
|
+ && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX
|
|
+ && rel->r_offset == rel[1].r_offset
|
|
+ && loongarch_can_trans_tls (abfd, info, h, r_symndx, r_type))
|
|
+ {
|
|
+ loongarch_tls_perform_trans (abfd, sec, rel, h, info);
|
|
+ r_type = ELFNN_R_TYPE (rel->r_info);
|
|
+ }
|
|
+
|
|
+ relax_func_t relax_func = NULL;
|
|
+ if (info->relax_pass == 0)
|
|
+ {
|
|
+ switch (r_type)
|
|
+ {
|
|
+ case R_LARCH_PCALA_HI20:
|
|
+ relax_func = loongarch_relax_pcala_addi;
|
|
+ break;
|
|
+ case R_LARCH_GOT_PC_HI20:
|
|
+ relax_func = loongarch_relax_pcala_ld;
|
|
+ break;
|
|
+ case R_LARCH_CALL36:
|
|
+ relax_func = loongarch_relax_call36;
|
|
+ break;
|
|
+ case R_LARCH_TLS_LE_HI20_R:
|
|
+ case R_LARCH_TLS_LE_LO12_R:
|
|
+ case R_LARCH_TLS_LE_ADD_R:
|
|
+ case R_LARCH_TLS_LE_HI20:
|
|
+ case R_LARCH_TLS_LE_LO12:
|
|
+ case R_LARCH_TLS_LE64_LO20:
|
|
+ case R_LARCH_TLS_LE64_HI12:
|
|
+ relax_func = loongarch_relax_tls_le;
|
|
+ break;
|
|
+ case R_LARCH_TLS_LD_PC_HI20:
|
|
+ case R_LARCH_TLS_GD_PC_HI20:
|
|
+ case R_LARCH_TLS_DESC_PC_HI20:
|
|
+ relax_func = loongarch_relax_tls_ld_gd_desc;
|
|
+ break;
|
|
+ default:
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ /* Only relax this reloc if it is paired with R_RISCV_RELAX. */
|
|
+ if (r_type == R_LARCH_TLS_LD_PC_HI20
|
|
+ || r_type == R_LARCH_TLS_GD_PC_HI20
|
|
+ || r_type == R_LARCH_TLS_DESC_PC_HI20
|
|
+ || r_type == R_LARCH_PCALA_HI20
|
|
+ || r_type == R_LARCH_GOT_PC_HI20)
|
|
+ {
|
|
+ if ((i + 2) == sec->reloc_count - 1
|
|
+ || ELFNN_R_TYPE ((rel + 1)->r_info) != R_LARCH_RELAX
|
|
+ || ELFNN_R_TYPE ((rel + 3)->r_info) != R_LARCH_RELAX
|
|
+ || rel->r_offset != (rel + 1)->r_offset
|
|
+ || (rel + 2)->r_offset != (rel + 3)->r_offset
|
|
+ || rel->r_offset + 4 != (rel + 2)->r_offset)
|
|
+ continue;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (i == sec->reloc_count - 1
|
|
+ || ELFNN_R_TYPE ((rel + 1)->r_info) != R_LARCH_RELAX
|
|
+ || rel->r_offset != (rel + 1)->r_offset)
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+ else if (info->relax_pass == 1 && r_type == R_LARCH_ALIGN)
|
|
+ relax_func = loongarch_relax_align;
|
|
+ else
|
|
+ continue;
|
|
+
|
|
/* Four kind of relocations:
|
|
Normal: symval is the symbol address.
|
|
R_LARCH_ALIGN: symval is the address of the last NOP instruction
|
|
@@ -5342,29 +5433,26 @@ 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)
|
|
continue;
|
|
|
|
/* Only TLS instruction sequences that are accompanied by
|
|
R_LARCH_RELAX and cannot perform type transition can be
|
|
relaxed. */
|
|
- if (R_LARCH_TLS_LD_PC_HI20 == r_type
|
|
- || R_LARCH_TLS_GD_PC_HI20 == r_type
|
|
- || (R_LARCH_TLS_DESC_PC_HI20 == r_type
|
|
- && (i + 1 != sec->reloc_count)
|
|
- && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX
|
|
- && ! loongarch_can_trans_tls (abfd, info, h,
|
|
- r_symndx, r_type)))
|
|
+ if (r_type == R_LARCH_TLS_LD_PC_HI20
|
|
+ || r_type == R_LARCH_TLS_GD_PC_HI20
|
|
+ || r_type == R_LARCH_TLS_DESC_PC_HI20)
|
|
{
|
|
sym_sec = htab->elf.sgot;
|
|
symval = elf_local_got_offsets (abfd)[r_symndx];
|
|
char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
|
|
r_symndx);
|
|
- if (R_LARCH_TLS_DESC_PC_HI20 == r_type
|
|
+ if (r_type == R_LARCH_TLS_DESC_PC_HI20
|
|
&& GOT_TLS_GD_BOTH_P (tls_type))
|
|
symval += 2 * GOT_ENTRY_SIZE;
|
|
}
|
|
- else if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
|
|
+ else if (sym->st_shndx == SHN_UNDEF || r_type == R_LARCH_ALIGN)
|
|
{
|
|
sym_sec = sec;
|
|
symval = rel->r_offset;
|
|
@@ -5375,35 +5463,25 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
|
|
symval = sym->st_value;
|
|
}
|
|
symtype = ELF_ST_TYPE (sym->st_info);
|
|
+ is_abs_symbol = sym->st_shndx == SHN_ABS;
|
|
}
|
|
else
|
|
{
|
|
- r_symndx = ELFNN_R_SYM (rel->r_info) - symtab_hdr->sh_info;
|
|
- h = elf_sym_hashes (abfd)[r_symndx];
|
|
-
|
|
- while (h->root.type == bfd_link_hash_indirect
|
|
- || h->root.type == bfd_link_hash_warning)
|
|
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
|
-
|
|
/* Disable the relaxation for ifunc. */
|
|
if (h != NULL && h->type == STT_GNU_IFUNC)
|
|
continue;
|
|
|
|
/* The GOT entry of tls symbols must in current execute file or
|
|
shared object. */
|
|
- if (R_LARCH_TLS_LD_PC_HI20 == r_type
|
|
- || R_LARCH_TLS_GD_PC_HI20 == r_type
|
|
- || (R_LARCH_TLS_DESC_PC_HI20 == r_type
|
|
- && (i + 1 != sec->reloc_count)
|
|
- && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX
|
|
- && !loongarch_can_trans_tls (abfd, info, h,
|
|
- r_symndx, r_type)))
|
|
+ if (r_type == R_LARCH_TLS_LD_PC_HI20
|
|
+ || r_type == R_LARCH_TLS_GD_PC_HI20
|
|
+ || r_type == R_LARCH_TLS_DESC_PC_HI20)
|
|
{
|
|
sym_sec = htab->elf.sgot;
|
|
symval = h->got.offset;
|
|
char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
|
|
r_symndx);
|
|
- if (R_LARCH_TLS_DESC_PC_HI20 == r_type
|
|
+ if (r_type == R_LARCH_TLS_DESC_PC_HI20
|
|
&& GOT_TLS_GD_BOTH_P (tls_type))
|
|
symval += 2 * GOT_ENTRY_SIZE;
|
|
}
|
|
@@ -5412,12 +5490,13 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
|
|
&& h->root.u.def.section != NULL
|
|
&& h->root.u.def.section->output_section != NULL)
|
|
{
|
|
- symval = h->root.u.def.value;
|
|
sym_sec = h->root.u.def.section;
|
|
+ symval = h->root.u.def.value;
|
|
}
|
|
else
|
|
continue;
|
|
|
|
+ is_abs_symbol = bfd_is_abs_section (h->root.u.def.section);
|
|
if (h && LARCH_REF_LOCAL (info, h))
|
|
local_got = true;
|
|
symtype = h->type;
|
|
@@ -5440,7 +5519,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
|
|
+ (alingmeng - 4).
|
|
If r_symndx is 0, alignmeng-4 is r_addend.
|
|
If r_symndx > 0, alignment-4 is 2^(r_addend & 0xff)-4. */
|
|
- else if (R_LARCH_ALIGN == r_type)
|
|
+ else if (r_type == R_LARCH_ALIGN)
|
|
if (r_symndx > 0)
|
|
symval += ((1 << (rel->r_addend & 0xff)) - 4);
|
|
else
|
|
@@ -5450,96 +5529,14 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
|
|
|
|
symval += sec_addr (sym_sec);
|
|
|
|
- /* If the conditions for tls type transition are met, type
|
|
- transition is performed instead of relax.
|
|
- During the transition from DESC->IE/LE, there are 2 situations
|
|
- depending on the different configurations of the relax/norelax
|
|
- option.
|
|
- If the -relax option is used, the extra nops will be removed,
|
|
- and this transition is performed in pass 0.
|
|
- If the --no-relax option is used, nop will be retained, and
|
|
- this transition is performed in pass 1. */
|
|
- if (IS_LOONGARCH_TLS_TRANS_RELOC (r_type)
|
|
- && (i + 1 != sec->reloc_count)
|
|
- && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX
|
|
- && loongarch_can_trans_tls (abfd, info, h, r_symndx, r_type))
|
|
- {
|
|
- loongarch_tls_perform_trans (abfd, sec, rel, h, info);
|
|
- r_type = ELFNN_R_TYPE (rel->r_info);
|
|
- }
|
|
-
|
|
- switch (r_type)
|
|
- {
|
|
- case R_LARCH_ALIGN:
|
|
- if (1 == info->relax_pass)
|
|
- loongarch_relax_align (abfd, sec, sym_sec, info, rel, symval);
|
|
- break;
|
|
+ if (r_type == R_LARCH_GOT_PC_HI20 && (!local_got || is_abs_symbol))
|
|
+ continue;
|
|
|
|
- case R_LARCH_DELETE:
|
|
- if (1 == info->relax_pass)
|
|
- {
|
|
- loongarch_relax_delete_bytes (abfd, sec, rel->r_offset, 4, info);
|
|
- rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
|
|
- }
|
|
- break;
|
|
- case R_LARCH_CALL36:
|
|
- if (0 == info->relax_pass && (i + 2) <= sec->reloc_count)
|
|
- loongarch_relax_call36 (abfd, sec, sym_sec, rel, symval,
|
|
+ if (relax_func (abfd, sec, sym_sec, rel, symval,
|
|
+ info, again, max_alignment)
|
|
+ && relax_func == loongarch_relax_pcala_ld)
|
|
+ loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval,
|
|
info, again, max_alignment);
|
|
- break;
|
|
-
|
|
- case R_LARCH_TLS_LE_HI20_R:
|
|
- case R_LARCH_TLS_LE_LO12_R:
|
|
- case R_LARCH_TLS_LE_ADD_R:
|
|
- case R_LARCH_TLS_LE_HI20:
|
|
- case R_LARCH_TLS_LE_LO12:
|
|
- case R_LARCH_TLS_LE64_LO20:
|
|
- case R_LARCH_TLS_LE64_HI12:
|
|
- if (0 == info->relax_pass && (i + 2) <= sec->reloc_count)
|
|
- loongarch_relax_tls_le (abfd, sec, rel, info, symval);
|
|
- break;
|
|
-
|
|
- case R_LARCH_PCALA_HI20:
|
|
- if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
|
|
- loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval,
|
|
- info, again, max_alignment);
|
|
- 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))
|
|
- loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval,
|
|
- info, again, max_alignment);
|
|
- }
|
|
- break;
|
|
-
|
|
- case R_LARCH_TLS_LD_PC_HI20:
|
|
- case R_LARCH_TLS_GD_PC_HI20:
|
|
- case R_LARCH_TLS_DESC_PC_HI20:
|
|
- if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
|
|
- loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
|
|
- info, again, max_alignment);
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
}
|
|
|
|
return true;
|
|
--
|
|
2.33.0
|
|
|