LoongArch: Add new relocs and macro for TLSDESC.

The normal DESC instruction sequence is:
  pcalau12i  $a0,%desc_pc_hi20(var)     #R_LARCH_TLS_DESC_PC_HI20
  addi.d     $a0,$a0,%desc_pc_lo12(var) #R_LARCH_TLS_DESC_PC_LO12
  ld.d       $ra,$a0,%desc_ld(var)	#R_LARCH_TLS_DESC_LD
  jirl       $ra,$ra,%desc_call(var)	#R_LARCH_TLS_DESC_CALL
  add.d	     $a0,$a0,$tp
This commit is contained in:
Lulu Cai 2023-10-31 16:11:29 +08:00 committed by liuzhensong
parent 051b3736af
commit 26265e7fdf
7 changed files with 349 additions and 4 deletions

View File

@ -7377,6 +7377,8 @@ enum bfd_reloc_code_real
BFD_RELOC_LARCH_TLS_DTPREL64,
BFD_RELOC_LARCH_TLS_TPREL32,
BFD_RELOC_LARCH_TLS_TPREL64,
BFD_RELOC_LARCH_TLS_DESC32,
BFD_RELOC_LARCH_TLS_DESC64,
BFD_RELOC_LARCH_MARK_LA,
BFD_RELOC_LARCH_MARK_PCREL,
BFD_RELOC_LARCH_SOP_PUSH_PCREL,
@ -7461,6 +7463,16 @@ enum bfd_reloc_code_real
BFD_RELOC_LARCH_SUB_ULEB128,
BFD_RELOC_LARCH_64_PCREL,
BFD_RELOC_LARCH_CALL36,
BFD_RELOC_LARCH_TLS_DESC_PC_HI20,
BFD_RELOC_LARCH_TLS_DESC_PC_LO12,
BFD_RELOC_LARCH_TLS_DESC64_PC_LO20,
BFD_RELOC_LARCH_TLS_DESC64_PC_HI12,
BFD_RELOC_LARCH_TLS_DESC_HI20,
BFD_RELOC_LARCH_TLS_DESC_LO12,
BFD_RELOC_LARCH_TLS_DESC64_LO20,
BFD_RELOC_LARCH_TLS_DESC64_HI12,
BFD_RELOC_LARCH_TLS_DESC_LD,
BFD_RELOC_LARCH_TLS_DESC_CALL,
BFD_RELOC_UNUSED
};
typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;

View File

@ -293,8 +293,40 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
NULL, /* adjust_reloc_bits */
NULL), /* larch_reloc_type_name */
LOONGARCH_EMPTY_HOWTO (13),
LOONGARCH_EMPTY_HOWTO (14),
LOONGARCH_HOWTO (R_LARCH_TLS_DESC32, /* type (13). */
0, /* rightshift. */
4, /* size. */
32, /* bitsize. */
false, /* pc_relative. */
0, /* bitpos. */
complain_overflow_dont, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_TLS_DESC32", /* name. */
false, /* partial_inplace. */
0, /* src_mask. */
ALL_ONES, /* dst_mask. */
false, /* pcrel_offset. */
BFD_RELOC_LARCH_TLS_DESC32, /* bfd_reloc_code_real_type. */
NULL, /* adjust_reloc_bits. */
NULL), /* larch_reloc_type_name. */
LOONGARCH_HOWTO (R_LARCH_TLS_DESC64, /* type (14). */
0, /* rightshift. */
4, /* size. */
64, /* bitsize. */
false, /* pc_relative. */
0, /* bitpos. */
complain_overflow_dont, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_TLS_DESC64", /* name. */
false, /* partial_inplace. */
0, /* src_mask. */
ALL_ONES, /* dst_mask. */
false, /* pcrel_offset. */
BFD_RELOC_LARCH_TLS_DESC64, /* bfd_reloc_code_real_type. */
NULL, /* adjust_reloc_bits. */
NULL), /* larch_reloc_type_name. */
LOONGARCH_EMPTY_HOWTO (15),
LOONGARCH_EMPTY_HOWTO (16),
LOONGARCH_EMPTY_HOWTO (17),
@ -1569,6 +1601,180 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
BFD_RELOC_LARCH_CALL36, /* bfd_reloc_code_real_type. */
reloc_sign_bits, /* adjust_reloc_bits. */
"call36"), /* larch_reloc_type_name. */
/* TLS_DESC PCREL. */
LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PC_HI20, /* type (111). */
12, /* rightshift. */
4, /* size. */
20, /* bitsize. */
true, /* pc_relative. */
5, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_TLS_DESC_PC_HI20", /* name. */
false, /* partial_inplace. */
0, /* src_mask. */
0x1ffffe0, /* dst_mask. */
false, /* pcrel_offset. */
BFD_RELOC_LARCH_TLS_DESC_PC_HI20, /* bfd_reloc_code_real_type. */
reloc_bits, /* adjust_reloc_bits. */
"desc_pc_hi20"), /* larch_reloc_type_name. */
LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PC_LO12, /* type (112). */
0, /* rightshift. */
4, /* size. */
12, /* bitsize. */
true, /* pc_relative. */
10, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_TLS_DESC_PC_LO12", /* name. */
false, /* partial_inplace. */
0, /* src_mask. */
0x3ffc00, /* dst_mask. */
false, /* pcrel_offset. */
BFD_RELOC_LARCH_TLS_DESC_PC_LO12, /* bfd_reloc_code_real_type. */
reloc_bits, /* adjust_reloc_bits. */
"desc_pc_lo12"), /* larch_reloc_type_name. */
/* TLS_DESC64 LARGE PCREL. */
LOONGARCH_HOWTO (R_LARCH_TLS_DESC64_PC_LO20, /* type (113). */
32, /* rightshift. */
8, /* size. */
20, /* bitsize. */
true, /* pc_relative. */
5, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_TLS_DESC64_PC_LO20", /* name. */
false, /* partial_inplace. */
0, /* src_mask. */
0x1ffffe0, /* dst_mask. */
false, /* pcrel_offset. */
BFD_RELOC_LARCH_TLS_DESC64_PC_LO20, /* bfd_reloc_code_real_type. */
reloc_bits, /* adjust_reloc_bits. */
"desc64_pc_lo20"), /* larch_reloc_type_name. */
LOONGARCH_HOWTO (R_LARCH_TLS_DESC64_PC_HI12, /* type (114). */
52, /* rightshift. */
8, /* size. */
12, /* bitsize. */
true, /* pc_relative. */
10, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_TLS_DESC64_PC_HI12", /* name. */
false, /* partial_inplace. */
0, /* src_mask. */
0x3ffc00, /* dst_mask. */
false, /* pcrel_offset. */
BFD_RELOC_LARCH_TLS_DESC64_PC_HI12, /* bfd_reloc_code_real_type. */
reloc_bits, /* adjust_reloc_bits. */
"desc64_pc_hi12"), /* larch_reloc_type_name. */
/* TLS_DESC ABS. */
LOONGARCH_HOWTO (R_LARCH_TLS_DESC_HI20, /* type (115). */
12, /* rightshift. */
4, /* size. */
20, /* bitsize. */
false, /* pc_relative. */
5, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_TLS_DESC_HI20", /* name. */
false, /* partial_inplace. */
0, /* src_mask. */
0x1ffffe0, /* dst_mask. */
false, /* pcrel_offset. */
BFD_RELOC_LARCH_TLS_DESC_HI20, /* bfd_reloc_code_real_type. */
reloc_bits, /* adjust_reloc_bits. */
"desc_hi20"), /* larch_reloc_type_name. */
LOONGARCH_HOWTO (R_LARCH_TLS_DESC_LO12, /* type (116). */
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_DESC_LO12", /* name. */
false, /* partial_inplace. */
0, /* src_mask. */
0x3ffc00, /* dst_mask. */
false, /* pcrel_offset. */
BFD_RELOC_LARCH_TLS_DESC_LO12, /* bfd_reloc_code_real_type. */
reloc_bits, /* adjust_reloc_bits. */
"desc_lo12"), /* larch_reloc_type_name. */
/* TLS_DESC64 LARGE ABS. */
LOONGARCH_HOWTO (R_LARCH_TLS_DESC64_LO20, /* type (117). */
32, /* rightshift. */
8, /* size. */
20, /* bitsize. */
false, /* pc_relative. */
5, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_TLS_DESC64_LO20", /* name. */
false, /* partial_inplace. */
0, /* src_mask. */
0x1ffffe0, /* dst_mask. */
false, /* pcrel_offset. */
BFD_RELOC_LARCH_TLS_DESC64_LO20, /* bfd_reloc_code_real_type. */
reloc_bits, /* adjust_reloc_bits. */
"desc64_lo20"), /* larch_reloc_type_name. */
LOONGARCH_HOWTO (R_LARCH_TLS_DESC64_HI12, /* type (118). */
52, /* rightshift. */
8, /* size. */
12, /* bitsize. */
false, /* pc_relative. */
10, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_TLS_DESC64_HI12", /* name. */
false, /* partial_inplace. */
0, /* src_mask. */
0x3ffc00, /* dst_mask. */
false, /* pcrel_offset. */
BFD_RELOC_LARCH_TLS_DESC64_HI12, /* bfd_reloc_code_real_type. */
reloc_bits, /* adjust_reloc_bits. */
"desc64_hi12"), /* larch_reloc_type_name. */
LOONGARCH_HOWTO (R_LARCH_TLS_DESC_LD, /* type (119). */
0, /* rightshift. */
4, /* size. */
0, /* bitsize. */
true, /* pc_relative. */
0, /* bitpos. */
complain_overflow_signed, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_TLS_DESC_LD", /* name. */
false, /* partial_inplace. */
0, /* src_mask. */
0, /* dst_mask. */
false, /* pcrel_offset. */
BFD_RELOC_LARCH_TLS_DESC_LD, /* bfd_reloc_code_real_type. */
NULL, /* adjust_reloc_bits. */
"desc_ld"), /* larch_reloc_type_name. */
LOONGARCH_HOWTO (R_LARCH_TLS_DESC_CALL, /* type (120). */
0, /* rightshift. */
4, /* size. */
0, /* bitsize. */
false, /* pc_relative. */
0, /* bitpos. */
complain_overflow_dont, /* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_LARCH_TLS_DESC_CALL", /* name. */
false, /* partial_inplace. */
0, /* src_mask. */
0, /* dst_mask. */
false, /* pcrel_offset. */
BFD_RELOC_LARCH_TLS_DESC_CALL, /* bfd_reloc_code_real_type. */
NULL, /* adjust_reloc_bits. */
"desc_call"), /* larch_reloc_type_name. */
};
reloc_howto_type *

View File

@ -3516,6 +3516,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_LARCH_TLS_DTPREL64",
"BFD_RELOC_LARCH_TLS_TPREL32",
"BFD_RELOC_LARCH_TLS_TPREL64",
"BFD_RELOC_LARCH_TLS_DESC32",
"BFD_RELOC_LARCH_TLS_DESC64",
"BFD_RELOC_LARCH_MARK_LA",
"BFD_RELOC_LARCH_MARK_PCREL",
"BFD_RELOC_LARCH_SOP_PUSH_PCREL",
@ -3600,6 +3602,16 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_LARCH_SUB_ULEB128",
"BFD_RELOC_LARCH_64_PCREL",
"BFD_RELOC_LARCH_CALL36",
"BFD_RELOC_LARCH_TLS_DESC_PC_HI20",
"BFD_RELOC_LARCH_TLS_DESC_PC_LO12",
"BFD_RELOC_LARCH_TLS_DESC64_PC_LO20",
"BFD_RELOC_LARCH_TLS_DESC64_PC_HI12",
"BFD_RELOC_LARCH_TLS_DESC_HI20",
"BFD_RELOC_LARCH_TLS_DESC_LO12",
"BFD_RELOC_LARCH_TLS_DESC64_LO20",
"BFD_RELOC_LARCH_TLS_DESC64_HI12",
"BFD_RELOC_LARCH_TLS_DESC_LD",
"BFD_RELOC_LARCH_TLS_DESC_CALL",
"@@overflow: BFD_RELOC_UNUSED@@",
};
#endif

View File

@ -8111,6 +8111,10 @@ ENUMX
BFD_RELOC_LARCH_TLS_TPREL32
ENUMX
BFD_RELOC_LARCH_TLS_TPREL64
ENUMX
BFD_RELOC_LARCH_TLS_DESC32
ENUMX
BFD_RELOC_LARCH_TLS_DESC64
ENUMX
BFD_RELOC_LARCH_MARK_LA
ENUMX
@ -8295,6 +8299,31 @@ ENUMX
ENUMX
BFD_RELOC_LARCH_CALL36
ENUMX
BFD_RELOC_LARCH_TLS_DESC_PC_HI20
ENUMX
BFD_RELOC_LARCH_TLS_DESC_PC_LO12
ENUMX
BFD_RELOC_LARCH_TLS_DESC64_PC_LO20
ENUMX
BFD_RELOC_LARCH_TLS_DESC64_PC_HI12
ENUMX
BFD_RELOC_LARCH_TLS_DESC_HI20
ENUMX
BFD_RELOC_LARCH_TLS_DESC_LO12
ENUMX
BFD_RELOC_LARCH_TLS_DESC64_LO20
ENUMX
BFD_RELOC_LARCH_TLS_DESC64_HI12
ENUMX
BFD_RELOC_LARCH_TLS_DESC_LD
ENUMX
BFD_RELOC_LARCH_TLS_DESC_CALL
ENUMDOC
LARCH relocations.

View File

@ -682,7 +682,7 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
esc_ch1, esc_ch2, bit_field, arg);
if (ip->reloc_info[0].type >= BFD_RELOC_LARCH_B16
&& ip->reloc_info[0].type < BFD_RELOC_UNUSED)
&& ip->reloc_info[0].type <= BFD_RELOC_LARCH_TLS_DESC_CALL)
{
/* As we compact stack-relocs, it is no need for pop operation.
But break out until here in order to check the imm field.
@ -1274,6 +1274,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
case BFD_RELOC_LARCH_TLS_LD_HI20:
case BFD_RELOC_LARCH_TLS_GD_PC_HI20:
case BFD_RELOC_LARCH_TLS_GD_HI20:
case BFD_RELOC_LARCH_TLS_DESC_PC_HI20:
case BFD_RELOC_LARCH_TLS_DESC_PC_LO12:
case BFD_RELOC_LARCH_TLS_DESC64_PC_LO20:
case BFD_RELOC_LARCH_TLS_DESC64_PC_HI12:
case BFD_RELOC_LARCH_TLS_DESC_HI20:
case BFD_RELOC_LARCH_TLS_DESC_LO12:
case BFD_RELOC_LARCH_TLS_DESC64_LO20:
case BFD_RELOC_LARCH_TLS_DESC64_HI12:
/* Add tls lo (got_lo reloc type). */
if (fixP->fx_addsy == NULL)
as_bad_where (fixP->fx_file, fixP->fx_line,
@ -1294,6 +1302,10 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
stack_top = 0;
break;
case BFD_RELOC_LARCH_TLS_DESC_LD:
case BFD_RELOC_LARCH_TLS_DESC_CALL:
break;
case BFD_RELOC_LARCH_SOP_POP_32_S_10_5:
case BFD_RELOC_LARCH_SOP_POP_32_S_10_12:
case BFD_RELOC_LARCH_SOP_POP_32_U_10_12:

View File

@ -38,7 +38,8 @@ RELOC_NUMBER (R_LARCH_TLS_DTPREL64, 9)
RELOC_NUMBER (R_LARCH_TLS_TPREL32, 10)
RELOC_NUMBER (R_LARCH_TLS_TPREL64, 11)
RELOC_NUMBER (R_LARCH_IRELATIVE, 12)
RELOC_NUMBER (R_LARCH_TLS_DESC32, 13)
RELOC_NUMBER (R_LARCH_TLS_DESC64, 14)
/* Reserved for future relocs that the dynamic linker must understand. */
/* Used by the static linker for relocating .text. */
@ -253,6 +254,25 @@ RELOC_NUMBER (R_LARCH_64_PCREL, 109)
RELOC_NUMBER (R_LARCH_CALL36, 110)
/* TLS_DESC PCREL. */
RELOC_NUMBER (R_LARCH_TLS_DESC_PC_HI20, 111)
RELOC_NUMBER (R_LARCH_TLS_DESC_PC_LO12, 112)
/* TLS_DESC LARGE PCREL. */
RELOC_NUMBER (R_LARCH_TLS_DESC64_PC_LO20, 113)
RELOC_NUMBER (R_LARCH_TLS_DESC64_PC_HI12, 114)
/* TLS_DESC ABS. */
RELOC_NUMBER (R_LARCH_TLS_DESC_HI20, 115)
RELOC_NUMBER (R_LARCH_TLS_DESC_LO12, 116)
/* TLSDESC LARGE ABS. */
RELOC_NUMBER (R_LARCH_TLS_DESC64_LO20, 117)
RELOC_NUMBER (R_LARCH_TLS_DESC64_HI12, 118)
RELOC_NUMBER (R_LARCH_TLS_DESC_LD, 119)
RELOC_NUMBER (R_LARCH_TLS_DESC_CALL, 120)
END_RELOC_NUMBERS (R_LARCH_count)
/* Processor specific flags for the ELF header e_flags field. */

View File

@ -303,6 +303,55 @@ const char *const loongarch_x_normal_name[32] =
"jirl $zero,%1,0;", \
0, 0
/* For TLS_DESC32 pcrel. */
#define INSN_LA_TLS_DESC32 \
"pcalau12i $r4,%%desc_pc_hi20(%2);" \
"addi.w $r4,$r4,%%desc_pc_lo12(%2);" \
"ld.w $r1,$r4,%%desc_ld(%2);" \
"jirl $r1,$r1,%%desc_call(%2);", \
&LARCH_opts.ase_ilp32, \
&LARCH_opts.ase_lp64
/* For TLS_DESC32 abs. */
#define INSN_LA_TLS_DESC32_ABS \
"lu12i.w $r4,%%desc_hi20(%2);" \
"ori $r4,$r4,%%desc_lo12(%2);" \
"ld.w $r1,$r4,%%desc_ld(%2);" \
"jirl $r1,$r1,%%desc_call(%2);", \
&LARCH_opts.ase_gabs, \
&LARCH_opts.ase_lp64
/* For TLS_DESC64 pcrel. */
#define INSN_LA_TLS_DESC64 \
"pcalau12i $r4,%%desc_pc_hi20(%2);" \
"addi.d $r4,$r4,%%desc_pc_lo12(%2);" \
"ld.d $r1,$r4,%%desc_ld(%2);" \
"jirl $r1,$r1,%%desc_call(%2);", \
&LARCH_opts.ase_lp64, 0
/* For TLS_DESC64 large pcrel. */
#define INSN_LA_TLS_DESC64_LARGE_PCREL \
"pcalau12i $r4,%%desc_pc_hi20(%3);" \
"addi.d %2,$r0,%%desc_pc_lo12(%3);" \
"lu32i.d %2,%%desc64_pc_lo20(%3);" \
"lu52i.d %2,%2,%%desc64_pc_hi12(%3);" \
"add.d $r4,$r4,%2;" \
"ld.d $r1,$r4,%%desc_ld(%3);" \
"jirl $r1,$r1,%%desc_call(%3);", \
&LARCH_opts.ase_lp64, \
&LARCH_opts.ase_gabs
/* For TLS_DESC64 large abs. */
#define INSN_LA_TLS_DESC64_LARGE_ABS \
"lu12i.w $r4,%%desc_hi20(%2);" \
"ori $r4,$r4,%%desc_lo12(%2);" \
"lu32i.d $r4,%%desc64_lo20(%2);" \
"lu52i.d $r4,$r4,%%desc64_hi12(%2);" \
"ld.d $r1,$r4,%%desc_ld(%2);" \
"jirl $r1,$r1,%%desc_call(%2);", \
&LARCH_opts.ase_gabs, \
&LARCH_opts.ase_gpcr
static struct loongarch_opcode loongarch_macro_opcodes[] =
{
/* match, mask, name, format, macro, include, exclude, pinfo. */
@ -352,6 +401,11 @@ static struct loongarch_opcode loongarch_macro_opcodes[] =
{ 0, 0, "call36", "la", INSN_LA_CALL, 0 },
{ 0, 0, "tail36", "r,la", INSN_LA_TAIL, 0 },
{ 0, 0, "pcaddi", "r,la", "pcaddi %1, %%pcrel_20(%2)", &LARCH_opts.ase_ilp32, 0, 0 },
{ 0, 0, "la.tls.desc", "r,l", INSN_LA_TLS_DESC32_ABS, 0 },
{ 0, 0, "la.tls.desc", "r,l", INSN_LA_TLS_DESC32, 0 },
{ 0, 0, "la.tls.desc", "r,l", INSN_LA_TLS_DESC64_LARGE_ABS, 0 },
{ 0, 0, "la.tls.desc", "r,l", INSN_LA_TLS_DESC64, 0 },
{ 0, 0, "la.tls.desc", "r,r,l", INSN_LA_TLS_DESC64_LARGE_PCREL,0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 } /* Terminate the list. */
};