forked from Imagelibrary/binutils-gdb
LoongArch: bfd: Add support for tls le relax.
Add tls le relax support and related relocs in bfd. New relocation related explanation can refer to the following url: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc This support does two main things: 1. Implement support for three new relocation items in bfd. The three new relocation items are shown below: R_LARCH_TLS_LE_ADD_R R_LARCH_TLS_LE_HI20_R R_LARCH_TLS_LE_LO12_R 2. ADD a new macro RELOCATE_TLS_TP32_HI20 Handle problems caused by symbol extensions in TLS LE, The processing is similar to the macro RELOCATE_CALC_PC32_HI20 method. 3. Implement the tls le relax function. bfd/ChangeLog: * bfd-in2.h: Add relocs related to tls le relax. * elfnn-loongarch.c: (loongarch_relax_tls_le): New function. (RELOCATE_TLS_TP32_HI20): New macro. (loongarch_elf_check_relocs): Add new reloc support. (perform_relocation): Likewise. (loongarch_elf_relocate_section): Handle new relocs related to relax. (loongarch_elf_relax_section): Likewise. * elfxx-loongarch.c: (LOONGARCH_HOWTO (R_LARCH_TLS_LE_ADD_R)): New reloc how to type. (LOONGARCH_HOWTO (R_LARCH_TLS_LE_HI20_R)): Likewise. (LOONGARCH_HOWTO (R_LARCH_TLS_LE_LO12_R)): Likewise. * libbfd.h: Add relocs related to tls le relax. * reloc.c: Likewise.
This commit is contained in:
committed by
liuzhensong
parent
77d242a06e
commit
aae8784c58
BIN
bfd/.elfnn-loongarch.c.swp
Normal file
BIN
bfd/.elfnn-loongarch.c.swp
Normal file
Binary file not shown.
@@ -7476,11 +7476,15 @@ enum bfd_reloc_code_real
|
|||||||
BFD_RELOC_LARCH_TLS_DESC64_HI12,
|
BFD_RELOC_LARCH_TLS_DESC64_HI12,
|
||||||
BFD_RELOC_LARCH_TLS_DESC_LD,
|
BFD_RELOC_LARCH_TLS_DESC_LD,
|
||||||
BFD_RELOC_LARCH_TLS_DESC_CALL,
|
BFD_RELOC_LARCH_TLS_DESC_CALL,
|
||||||
|
BFD_RELOC_LARCH_TLS_LE_HI20_R,
|
||||||
|
BFD_RELOC_LARCH_TLS_LE_ADD_R,
|
||||||
|
BFD_RELOC_LARCH_TLS_LE_LO12_R,
|
||||||
BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,
|
BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,
|
||||||
BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,
|
BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,
|
||||||
BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,
|
BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,
|
||||||
BFD_RELOC_UNUSED
|
BFD_RELOC_UNUSED
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
|
typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
|
||||||
|
|
||||||
reloc_howto_type *bfd_reloc_type_lookup
|
reloc_howto_type *bfd_reloc_type_lookup
|
||||||
|
|||||||
@@ -858,6 +858,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case R_LARCH_TLS_LE_HI20:
|
case R_LARCH_TLS_LE_HI20:
|
||||||
|
case R_LARCH_TLS_LE_HI20_R:
|
||||||
case R_LARCH_SOP_PUSH_TLS_TPREL:
|
case R_LARCH_SOP_PUSH_TLS_TPREL:
|
||||||
if (!bfd_link_executable (info))
|
if (!bfd_link_executable (info))
|
||||||
return false;
|
return false;
|
||||||
@@ -2261,6 +2262,8 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
|
|||||||
case R_LARCH_GOT64_HI12:
|
case R_LARCH_GOT64_HI12:
|
||||||
case R_LARCH_TLS_LE_HI20:
|
case R_LARCH_TLS_LE_HI20:
|
||||||
case R_LARCH_TLS_LE_LO12:
|
case R_LARCH_TLS_LE_LO12:
|
||||||
|
case R_LARCH_TLS_LE_HI20_R:
|
||||||
|
case R_LARCH_TLS_LE_LO12_R:
|
||||||
case R_LARCH_TLS_LE64_LO20:
|
case R_LARCH_TLS_LE64_LO20:
|
||||||
case R_LARCH_TLS_LE64_HI12:
|
case R_LARCH_TLS_LE64_HI12:
|
||||||
case R_LARCH_TLS_IE_PC_HI20:
|
case R_LARCH_TLS_IE_PC_HI20:
|
||||||
@@ -2303,6 +2306,7 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case R_LARCH_RELAX:
|
case R_LARCH_RELAX:
|
||||||
|
case R_LARCH_TLS_LE_ADD_R:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -2483,6 +2487,16 @@ loongarch_reloc_is_fatal (struct bfd_link_info *info,
|
|||||||
relocation += 0x1000; \
|
relocation += 0x1000; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/* Handle problems caused by symbol extensions in TLS LE, The processing
|
||||||
|
is similar to the macro RELOCATE_CALC_PC32_HI20 method. */
|
||||||
|
#define RELOCATE_TLS_TP32_HI20(relocation) \
|
||||||
|
({ \
|
||||||
|
bfd_vma __lo = (relocation) & ((bfd_vma)0xfff); \
|
||||||
|
if (__lo > 0x7ff) \
|
||||||
|
relocation += 0x800; \
|
||||||
|
relocation = relocation & ~(bfd_vma)0xfff; \
|
||||||
|
})
|
||||||
|
|
||||||
/* For example: pc is 0x11000010000100, symbol is 0x1812348ffff812
|
/* For example: pc is 0x11000010000100, symbol is 0x1812348ffff812
|
||||||
offset = (0x1812348ffff812 & ~0xfff) - (0x11000010000100 & ~0xfff)
|
offset = (0x1812348ffff812 & ~0xfff) - (0x11000010000100 & ~0xfff)
|
||||||
= 0x712347ffff000
|
= 0x712347ffff000
|
||||||
@@ -3481,6 +3495,13 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case R_LARCH_TLS_LE_HI20_R:
|
||||||
|
relocation -= elf_hash_table (info)->tls_sec->vma;
|
||||||
|
|
||||||
|
RELOCATE_TLS_TP32_HI20 (relocation);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case R_LARCH_PCALA_LO12:
|
case R_LARCH_PCALA_LO12:
|
||||||
/* Not support if sym_addr in 2k page edge.
|
/* Not support if sym_addr in 2k page edge.
|
||||||
pcalau12i pc_hi20 (sym_addr)
|
pcalau12i pc_hi20 (sym_addr)
|
||||||
@@ -3651,6 +3672,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
|
|||||||
|
|
||||||
case R_LARCH_TLS_LE_HI20:
|
case R_LARCH_TLS_LE_HI20:
|
||||||
case R_LARCH_TLS_LE_LO12:
|
case R_LARCH_TLS_LE_LO12:
|
||||||
|
case R_LARCH_TLS_LE_LO12_R:
|
||||||
case R_LARCH_TLS_LE64_LO20:
|
case R_LARCH_TLS_LE64_LO20:
|
||||||
case R_LARCH_TLS_LE64_HI12:
|
case R_LARCH_TLS_LE64_HI12:
|
||||||
BFD_ASSERT (resolved_local && elf_hash_table (info)->tls_sec);
|
BFD_ASSERT (resolved_local && elf_hash_table (info)->tls_sec);
|
||||||
@@ -4089,6 +4111,82 @@ loongarch_relax_delete_bytes (bfd *abfd,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
/* Relax tls le, mainly relax the process of getting TLS le symbolic addresses.
|
||||||
|
there are three situations in which an assembly instruction sequence needs to
|
||||||
|
be relaxed:
|
||||||
|
symbol address = tp + offset (symbol),offset (symbol) = le_hi20_r + le_lo12_r
|
||||||
|
|
||||||
|
Case 1:
|
||||||
|
in this case, the rd register in the st.{w/d} instruction does not store the
|
||||||
|
full tls symbolic address, but tp + le_hi20_r, which is a part of the tls
|
||||||
|
symbolic address, and then obtains the rd + le_lo12_r address through the
|
||||||
|
st.w instruction feature.
|
||||||
|
this is the full tls symbolic address (tp + le_hi20_r + le_lo12_r).
|
||||||
|
|
||||||
|
before relax: after relax:
|
||||||
|
|
||||||
|
lu12i.w $rd,%le_hi20_r (sym) ==> (instruction deleted)
|
||||||
|
add.{w/d} $rd,$rd,$tp,%le_add_r (sym) ==> (instruction deleted)
|
||||||
|
st.{w/d} $rs,$rd,%le_lo12_r (sym) ==> st.{w/d} $rs,$tp,%le_lo12_r (sym)
|
||||||
|
|
||||||
|
Case 2:
|
||||||
|
in this case, ld.{w/d} is similar to st.{w/d} in case1.
|
||||||
|
|
||||||
|
before relax: after relax:
|
||||||
|
|
||||||
|
lu12i.w $rd,%le_hi20_r (sym) ==> (instruction deleted)
|
||||||
|
add.{w/d} $rd,$rd,$tp,%le_add_r (sym) ==> (instruction deleted)
|
||||||
|
ld.{w/d} $rs,$rd,%le_lo12_r (sym) ==> ld.{w/d} $rs,$tp,%le_lo12_r (sym)
|
||||||
|
|
||||||
|
Case 3:
|
||||||
|
in this case,the rs register in addi.{w/d} stores the full address of the tls
|
||||||
|
symbol (tp + le_hi20_r + le_lo12_r).
|
||||||
|
|
||||||
|
before relax: after relax:
|
||||||
|
|
||||||
|
lu12i.w $rd,%le_hi20_r (sym) ==> (instruction deleted)
|
||||||
|
add.{w/d} $rd,$rd,$tp,%le_add_r (sym) ==> (instruction deleted)
|
||||||
|
addi.{w/d} $rs,$rd,%le_lo12_r (sym) ==> addi.{w/d} $rs,$tp,%le_lo12_r (sym)
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
loongarch_relax_tls_le (bfd *abfd, asection *sec,
|
||||||
|
Elf_Internal_Rela *rel,
|
||||||
|
struct bfd_link_info *link_info,
|
||||||
|
bfd_vma symval)
|
||||||
|
{
|
||||||
|
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
|
||||||
|
uint32_t insn = bfd_get (32, abfd, contents + rel->r_offset);
|
||||||
|
static uint32_t insn_rj,insn_rd;
|
||||||
|
symval = symval - elf_hash_table (link_info)->tls_sec->vma;
|
||||||
|
/* Whether the symbol offset is in the interval (offset < 0x800). */
|
||||||
|
if (ELFNN_R_TYPE ((rel + 1)->r_info == R_LARCH_RELAX) && (symval < 0x800))
|
||||||
|
{
|
||||||
|
switch (ELFNN_R_TYPE (rel->r_info))
|
||||||
|
{
|
||||||
|
case R_LARCH_TLS_LE_HI20_R:
|
||||||
|
case R_LARCH_TLS_LE_ADD_R:
|
||||||
|
/* delete insn. */
|
||||||
|
rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
|
||||||
|
loongarch_relax_delete_bytes (abfd, sec, rel->r_offset, 4, link_info);
|
||||||
|
break;
|
||||||
|
case R_LARCH_TLS_LE_LO12_R:
|
||||||
|
/* Change rj to $tp. */
|
||||||
|
insn_rj = 0x2 << 5;
|
||||||
|
/* Get rd register. */
|
||||||
|
insn_rd = insn & 0x1f;
|
||||||
|
/* Write symbol offset. */
|
||||||
|
symval <<= 10;
|
||||||
|
/* Writes the modified instruction. */
|
||||||
|
insn = insn & 0xffc00000;
|
||||||
|
insn = insn | symval | insn_rj | insn_rd;
|
||||||
|
bfd_put (32, abfd, insn, contents + rel->r_offset);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Relax pcalau12i,addi.d => pcaddi. */
|
/* Relax pcalau12i,addi.d => pcaddi. */
|
||||||
static bool
|
static bool
|
||||||
@@ -4518,6 +4616,13 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
|
|||||||
rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
|
rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case R_LARCH_TLS_LE_HI20_R:
|
||||||
|
case R_LARCH_TLS_LE_LO12_R:
|
||||||
|
case R_LARCH_TLS_LE_ADD_R:
|
||||||
|
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:
|
case R_LARCH_PCALA_HI20:
|
||||||
if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
|
if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
|
||||||
loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval,
|
loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval,
|
||||||
|
|||||||
@@ -1776,9 +1776,56 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
|
|||||||
NULL, /* adjust_reloc_bits. */
|
NULL, /* adjust_reloc_bits. */
|
||||||
"desc_call"), /* larch_reloc_type_name. */
|
"desc_call"), /* larch_reloc_type_name. */
|
||||||
|
|
||||||
LOONGARCH_EMPTY_HOWTO (121),
|
LOONGARCH_HOWTO (R_LARCH_TLS_LE_HI20_R, /* type (121). */
|
||||||
LOONGARCH_EMPTY_HOWTO (122),
|
12, /* rightshift. */
|
||||||
LOONGARCH_EMPTY_HOWTO (123),
|
4, /* size. */
|
||||||
|
20, /* bitsize. */
|
||||||
|
false, /* pc_relative. */
|
||||||
|
5, /* bitpos. */
|
||||||
|
complain_overflow_signed, /* complain_on_overflow. */
|
||||||
|
bfd_elf_generic_reloc, /* special_function. */
|
||||||
|
"R_LARCH_TLS_LE_HI20_R", /* name. */
|
||||||
|
false, /* partial_inplace. */
|
||||||
|
0, /* src_mask. */
|
||||||
|
0x1ffffe0, /* dst_mask. */
|
||||||
|
false, /* pcrel_offset. */
|
||||||
|
BFD_RELOC_LARCH_TLS_LE_HI20_R, /* bfd_reloc_code_real_type. */
|
||||||
|
reloc_bits, /* adjust_reloc_bits. */
|
||||||
|
"le_hi20_r"), /* larch_reloc_type_name. */
|
||||||
|
|
||||||
|
LOONGARCH_HOWTO (R_LARCH_TLS_LE_ADD_R, /* type (122). */
|
||||||
|
0, /* rightshift. */
|
||||||
|
0, /* size. */
|
||||||
|
0, /* bitsize. */
|
||||||
|
false, /* pc_relative. */
|
||||||
|
0, /* bitpos. */
|
||||||
|
complain_overflow_dont, /* complain_on_overflow. */
|
||||||
|
bfd_elf_generic_reloc, /* special_function. */
|
||||||
|
"R_LARCH_TLS_LE_ADD_R", /* name. */
|
||||||
|
false, /* partial_inplace. */
|
||||||
|
0, /* src_mask. */
|
||||||
|
0, /* dst_mask. */
|
||||||
|
false, /* pcrel_offset. */
|
||||||
|
BFD_RELOC_LARCH_TLS_LE_ADD_R, /* bfd_reloc_code_real_type. */
|
||||||
|
NULL, /* adjust_reloc_bits. */
|
||||||
|
"le_add_r"), /* larch_reloc_type_name. */
|
||||||
|
|
||||||
|
LOONGARCH_HOWTO (R_LARCH_TLS_LE_LO12_R, /* type (123). */
|
||||||
|
0, /* rightshift. */
|
||||||
|
4, /* size. */
|
||||||
|
12, /* bitsize. */
|
||||||
|
false, /* pc_relative. */
|
||||||
|
10, /* bitpos. */
|
||||||
|
complain_overflow_signed, /* complain_on_overflow. */
|
||||||
|
bfd_elf_generic_reloc, /* special_function. */
|
||||||
|
"R_LARCH_TLS_LE_LO12_R", /* name. */
|
||||||
|
false, /* partial_inplace. */
|
||||||
|
0, /* src_mask. */
|
||||||
|
0x3ffc00, /* dst_mask. */
|
||||||
|
false, /* pcrel_offset. */
|
||||||
|
BFD_RELOC_LARCH_TLS_LE_LO12_R, /* bfd_reloc_code_real_type. */
|
||||||
|
reloc_bits, /* adjust_reloc_bits. */
|
||||||
|
"le_lo12_r"), /* larch_reloc_type_name. */
|
||||||
|
|
||||||
/* For pcaddi, ld_pc_hi20 + ld_pc_lo12 can relax to ld_pcrel20_s2. */
|
/* For pcaddi, ld_pc_hi20 + ld_pc_lo12 can relax to ld_pcrel20_s2. */
|
||||||
LOONGARCH_HOWTO (R_LARCH_TLS_LD_PCREL20_S2, /* type (124). */
|
LOONGARCH_HOWTO (R_LARCH_TLS_LD_PCREL20_S2, /* type (124). */
|
||||||
@@ -1870,9 +1917,7 @@ reloc_howto_type *
|
|||||||
loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
|
loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
|
||||||
bfd_reloc_code_real_type code)
|
bfd_reloc_code_real_type code)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
|
BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
|
||||||
*/
|
|
||||||
|
|
||||||
/* Fast search for new reloc types. */
|
/* Fast search for new reloc types. */
|
||||||
if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX)
|
if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX)
|
||||||
|
|||||||
@@ -3615,6 +3615,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
|||||||
"BFD_RELOC_LARCH_TLS_DESC64_HI12",
|
"BFD_RELOC_LARCH_TLS_DESC64_HI12",
|
||||||
"BFD_RELOC_LARCH_TLS_DESC_LD",
|
"BFD_RELOC_LARCH_TLS_DESC_LD",
|
||||||
"BFD_RELOC_LARCH_TLS_DESC_CALL",
|
"BFD_RELOC_LARCH_TLS_DESC_CALL",
|
||||||
|
"BFD_RELOC_LARCH_TLS_LE_HI20_R",
|
||||||
|
"BFD_RELOC_LARCH_TLS_LE_ADD_R",
|
||||||
|
"BFD_RELOC_LARCH_TLS_LE_LO12_R",
|
||||||
"BFD_RELOC_LARCH_TLS_LD_PCREL20_S2",
|
"BFD_RELOC_LARCH_TLS_LD_PCREL20_S2",
|
||||||
"BFD_RELOC_LARCH_TLS_GD_PCREL20_S2",
|
"BFD_RELOC_LARCH_TLS_GD_PCREL20_S2",
|
||||||
"BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2",
|
"BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2",
|
||||||
|
|||||||
@@ -8330,6 +8330,13 @@ ENUMX
|
|||||||
ENUMX
|
ENUMX
|
||||||
BFD_RELOC_LARCH_TLS_DESC_CALL
|
BFD_RELOC_LARCH_TLS_DESC_CALL
|
||||||
|
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_LARCH_TLS_LE_HI20_R
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_LARCH_TLS_LE_ADD_R
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_LARCH_TLS_LE_LO12_R
|
||||||
|
|
||||||
ENUMX
|
ENUMX
|
||||||
BFD_RELOC_LARCH_TLS_LD_PCREL20_S2
|
BFD_RELOC_LARCH_TLS_LD_PCREL20_S2
|
||||||
ENUMX
|
ENUMX
|
||||||
|
|||||||
Reference in New Issue
Block a user