From: Lulu Cai <cailulu@loongson.cn>
To: Tatsuyuki Ishi <ishitatsuyuki@gmail.com>
Cc: binutils@sourceware.org, xuchenghua@loongson.cn,
chenglulu@loongson.cn, liuzhensong@loongson.cn,
mengqinggang@loongson.cn, xry111@xry111.site,
i.swmail@xen0n.name, maskray@google.com, luweining@loongson.cn,
wanglei@loongson.cn, hejinyang@loongson.cn
Subject: Re: [PATCH v5 3/5] LoongArch: Add tls transition support.
Date: Fri, 29 Dec 2023 18:31:41 +0800 [thread overview]
Message-ID: <cdda1f13-aabe-00ec-1ac0-1ba40847d04b@loongson.cn> (raw)
In-Reply-To: <1009A114-315F-4E1A-9642-BE9AD0E48B28@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 11312 bytes --]
On 2023/12/28 at 10:42 PM, Tatsuyuki Ishi Wrote:
>> On Dec 22, 2023, at 20:42, Lulu Cai <cailulu@loongson.cn> wrote:
>>
>> Transitions between DESC->IE/LE and IE->LE are supported now.
>> 1. For DESC -> LE:
>> pcalau12i $a0,%desc_pc_hi20(var) => lu12i.w $a0,%le_hi20(var)
>> addi.d $a0,$a0,%desc_pc_lo12(var) => ori $a0,$a0,%le_lo12(var)
>> ld.d $a1,$a0,%desc_ld(var) => NOP
>> jirl $ra,$a1,%desc_call(var)=> NOP
>> add.d $a0,$a0,$tp
>> 2. For DESC -> IE:
>> pcalau12i $a0,%desc_pc_hi20(var) => pcalau12i
>> $a0,%ie_pc_hi20(var)
>> addi.d $a0,$a0,%desc_pc_lo12(var) => ld.d $a0,$a0,%ie_pc_lo12(var)
>> ld.d $a1,$a0,%desc_ld(var) => NOP
>> jirl $ra,$a1,%desc_call(var)=> NOP
>> add.d $a0,$a0,$tp
>> 3. For IE -> LE:
>> pcalau12i $a0,%ie_pc_hi20(var) => lu12i.w $a0,%le_hi20(var)
>> ld.d $a0,$a0,%ie_pc_lo12(var) => ori $a0,$a0,%le_lo12(var)
>> add.d $a0,$a0,$tp
>> 4. When a tls variable is accessed using both DESC and IE, DESC
>> transitions
>> to IE and uses the same GOT entry as IE.
>> ---
>> bfd/elfnn-loongarch.c | 216 ++++++++++++++++++++++++++++++++++++-
>> include/opcode/loongarch.h | 6 ++
>> 2 files changed, 221 insertions(+), 1 deletion(-)
>>
>> diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
>> index 95a39148f73..1347d13d2e2 100644
>> --- a/bfd/elfnn-loongarch.c
>> +++ b/bfd/elfnn-loongarch.c
>> @@ -145,6 +145,16 @@ struct loongarch_elf_link_hash_table
>> #define elf_backend_rela_normal 1
>> #define elf_backend_default_execstack 0
>>
>> +#define IS_LOONGARCH_TLS_DESC_RELOC(R_TYPE) \
>> + ((R_TYPE) == R_LARCH_TLS_DESC_PC_HI20\
>> + || (R_TYPE) == R_LARCH_TLS_DESC_PC_LO12 \
>> + || (R_TYPE) == R_LARCH_TLS_DESC_LD \
>> + || (R_TYPE) == R_LARCH_TLS_DESC_CALL)
>> +
>> +#define IS_LOONGARCH_TLS_IE_RELOC(R_TYPE) \
>> + ((R_TYPE) == R_LARCH_TLS_IE_PC_HI20 \
>> + || (R_TYPE) == R_LARCH_TLS_IE_PC_LO12)
>> +
>> /* Generate a PLT header. */
>>
>> static bool
>> @@ -593,6 +603,10 @@ loongarch_elf_record_tls_and_got_reference (bfd
>> *abfd,
>>
>> char *new_tls_type = &_bfd_loongarch_elf_tls_type (abfd, h, symndx);
>> *new_tls_type |= tls_type;
>> +
>> + /* If a symbol is accessed by both IE and DESC, relax DESC to IE. */
>> + if ((*new_tls_type & GOT_TLS_IE) && (*new_tls_type & GOT_TLS_GDESC))
>> + *new_tls_type &= ~ (GOT_TLS_GDESC);
>> if ((*new_tls_type & GOT_NORMAL) && (*new_tls_type & ~GOT_NORMAL))
>> {
>> _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
>> @@ -605,6 +619,104 @@ loongarch_elf_record_tls_and_got_reference (bfd
>> *abfd,
>> return true;
>> }
>>
>> +static unsigned int
>> +loongarch_reloc_got_type (unsigned int r_type)
>> +{
>> + switch (r_type)
>> + {
>> + case R_LARCH_TLS_DESC_PC_HI20:
>> + case R_LARCH_TLS_DESC_PC_LO12:
>> + case R_LARCH_TLS_DESC_LD:
>> + case R_LARCH_TLS_DESC_CALL:
>> +return GOT_TLS_GDESC;
>> +
>> + case R_LARCH_TLS_IE_PC_HI20:
>> + case R_LARCH_TLS_IE_PC_LO12:
>> +return GOT_TLS_IE;
>> +
>> + default:
>> +break;
>
> I would expect the function to cover GD and LE too. See remark about
> relaxation below though.
>
I may add it in a later version.
>> + }
>> + return GOT_UNKNOWN;
>> +}
>> +
>> +/* Return true if tls type transition can be performed. */
>> +static bool
>> +loongarch_can_relax_tls (struct bfd_link_info *info, unsigned int
>> r_type,
>> +struct elf_link_hash_entry *h, bfd *input_bfd,
>> +unsigned long r_symndx)
>> +{
>> + char symbol_tls_type;
>> + unsigned int reloc_got_type;
>> +
>> + if (! (IS_LOONGARCH_TLS_DESC_RELOC (r_type)
>> +|| IS_LOONGARCH_TLS_IE_RELOC (r_type)))
>> + return false;
>> +
>> + symbol_tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h,
>> r_symndx);
>> + reloc_got_type = loongarch_reloc_got_type (r_type);
>> +
>> + if (symbol_tls_type == GOT_TLS_IE && GOT_TLS_GD_ANY_P
>> (reloc_got_type))
>> + return true;
>
> Per the suggestion above, if you add TLS_GD into the return value of
> loongarch_reloc_got_type, you might want to double check if GD -> IE
> relaxation is possible. (This was not the case for RISC-V.)
GD->LE relaxation is not possible on LoongArch because the location of
bl %plt(__tls_get_addr) cannot be determined.
>
>> +
>> + if (! bfd_link_executable (info))
>> + return false;
>> +
>> + if (h && h->root.type == bfd_link_hash_undefweak)
>> + return false;
>> +
>> + return true;
>> +}
>> +
>> +/* The type of relocation that can be transitioned. */
>> +static unsigned int
>> +loongarch_tls_transition_without_check (struct bfd_link_info *info,
>> +unsigned int r_type,
>> +struct elf_link_hash_entry *h)
>> +{
>> + bool local_exec = bfd_link_executable (info)
>> + && SYMBOL_REFERENCES_LOCAL (info, h);
>> +
>> + switch (r_type)
>> + {
>> + case R_LARCH_TLS_DESC_PC_HI20:
>> +return (local_exec
>> +? R_LARCH_TLS_LE_HI20
>> +: R_LARCH_TLS_IE_PC_HI20);
>> +
>> + case R_LARCH_TLS_DESC_PC_LO12:
>> +return (local_exec
>> +? R_LARCH_TLS_LE_LO12
>> +: R_LARCH_TLS_IE_PC_LO12);
>> +
>> + case R_LARCH_TLS_DESC_LD:
>> + case R_LARCH_TLS_DESC_CALL:
>> +return R_LARCH_NONE;
>> +
>> + case R_LARCH_TLS_IE_PC_HI20:
>> +return local_exec ? R_LARCH_TLS_LE_HI20 : r_type;
>> +
>> + case R_LARCH_TLS_IE_PC_LO12:
>> +return local_exec ? R_LARCH_TLS_LE_LO12 : r_type;
>> +
>> + default:
>> +break;
>> + }
>> +
>> + return r_type;
>> +}
>> +
>> +static unsigned int
>> +loongarch_tls_transition (struct bfd_link_info *info, unsigned int
>> r_type,
>> + struct elf_link_hash_entry *h, bfd *input_bfd,
>> + unsigned long r_symndx)
>> +{
>> + if (! loongarch_can_relax_tls (info, r_type, h, input_bfd,r_symndx))
>> + return r_type;
>> +
>> + return loongarch_tls_transition_without_check (info, r_type, h);
>> +}
>> +
>> /* Look through the relocs for a section during the first phase, and
>> allocate space in the global offset table or procedure linkage
>> table. */
>> @@ -706,6 +818,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct
>> bfd_link_info *info,
>> int need_dynreloc = 0;
>> int only_need_pcrel = 0;
>>
>> + r_type = loongarch_tls_transition (info, r_type, h, abfd,
>> r_symndx);
>> switch (r_type)
>> {
>> case R_LARCH_GOT_PC_HI20:
>> @@ -2403,6 +2516,96 @@ loongarch_reloc_is_fatal (struct bfd_link_info
>> *info,
>> relocation += 0x100000000;\
>> })
>>
>> +/* Transition instruction sequence to relax instruction sequence. */
>> +static bool
>> +loongarch_tls_relax (bfd *abfd, asection *sec, Elf_Internal_Rela *rel,
>> + int r_type, struct elf_link_hash_entry *h,
>> + struct bfd_link_info *info)
>> +{
>> + bool local_exec = bfd_link_executable (info)
>> + && SYMBOL_REFERENCES_LOCAL (info, h);
>> + bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
>> + unsigned long insn;
>> +
>> + switch (r_type)
>> + {
>> + case R_LARCH_TLS_DESC_PC_HI20:
>> +if (local_exec)
>> + /* DESC -> LE relaxation:
>> + pcalalau12i $a0,%desc_pc_hi20(var) =>
>> + lu12i.w $a0,%le_hi20(var)
>> + */
>> + bfd_put (32, abfd, LARCH_LU12I_W | LARCH_RD_A0,
>> + contents + rel->r_offset);
>> +
>> +/* DESC -> IE relaxation:
>> + pcalalau12i $a0,%desc_pc_hi20(var) =>
>> + pcalalau12i $a0,%ie_pc_hi20(var)
>> +*/
>> +return true;
>> +
>> + case R_LARCH_TLS_DESC_PC_LO12:
>> +if (local_exec)
>> + {
>> + /* DESC -> LE relaxation:
>> + addi.d $a0,$a0,%desc_pc_lo12(var) =>
>> + ori $a0,$a0,le_lo12(var)
>> + */
>> + insn = LARCH_ORI | LARCH_RD_RJ_A0;
>> + bfd_put (32, abfd, LARCH_ORI | LARCH_RD_RJ_A0,
>> + contents + rel->r_offset);
>> + }
>> +else
>> + {
>> + /* DESC -> IE relaxation:
>> + addi.d $a0,$a0,%desc_pc_lo12(var) =>
>> + ld.d $a0,$a0,%%ie_pc_lo12
>> + */
>> + bfd_put (32, abfd, LARCH_LD_D | LARCH_RD_RJ_A0,
>> + contents + rel->r_offset);
>> + }
>> +return true;
>> +
>> + case R_LARCH_TLS_DESC_LD:
>> + case R_LARCH_TLS_DESC_CALL:
>> +/* DESC -> LE/IE relaxation:
>> + ld.d $ra,$a0,%desc_ld(var) => NOP
>> + jirl $ra,$ra,%desc_call(var) => NOP
>> +*/
>> +bfd_put (32, abfd, LARCH_NOP, contents + rel->r_offset);
>> +return true;
>> +
>> + case R_LARCH_TLS_IE_PC_HI20:
>> +if (local_exec)
>> + {
>> + /* IE -> LE relaxation:
>> + pcalalau12i $rd,%ie_pc_hi20(var) =>
>> + lu12i.w $rd,%le_hi20(var)
>> + */
>> + insn = bfd_getl32 (contents + rel->r_offset);
>> + bfd_put (32, abfd, LARCH_LU12I_W | (insn & 0x1f),
>> + contents + rel->r_offset);
>> + }
>> +return true;
>> +
>> + case R_LARCH_TLS_IE_PC_LO12:
>> +if (local_exec)
>> + {
>> + /* IE -> LE relaxation:
>> + ld.d $rd,$rj,%%ie_pc_lo12 =>
>> + ori $rd,$rj,le_lo12(var)
>> + */
>> + insn = bfd_getl32 (contents + rel->r_offset);
>> + bfd_put (32, abfd, LARCH_ORI | (insn & 0x3ff),
>> + contents + rel->r_offset);
>> + }
>> +return true;
>> + }
>> +
>> + return false;
>> +}
>> +
>> +
>> static int
>> loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info
>> *info,
>> bfd *input_bfd, asection *input_section,
>> @@ -2426,7 +2629,7 @@ loongarch_elf_relocate_section (bfd
>> *output_bfd, struct bfd_link_info *info,
>> relend = relocs + input_section->reloc_count;
>> for (rel = relocs; rel < relend; rel++)
>> {
>> - int r_type = ELFNN_R_TYPE (rel->r_info);
>> + unsigned int r_type = ELFNN_R_TYPE (rel->r_info);
>> unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>> bfd_vma pc = sec_addr (input_section) + rel->r_offset;
>> reloc_howto_type *howto = NULL;
>> @@ -2436,6 +2639,7 @@ loongarch_elf_relocate_section (bfd
>> *output_bfd, struct bfd_link_info *info,
>> const char *name;
>> bfd_reloc_status_type r = bfd_reloc_ok;
>> bool is_ie, is_desc, is_undefweak, unresolved_reloc, defined_local;
>> + unsigned int relaxed_r_type;
>> bool resolved_local, resolved_dynly, resolved_to_const;
>> char tls_type;
>> bfd_vma relocation, off, ie_off, desc_off;
>> @@ -2567,6 +2771,16 @@ loongarch_elf_relocate_section (bfd
>> *output_bfd, struct bfd_link_info *info,
>>
>> BFD_ASSERT (!resolved_local || defined_local);
>>
>> + relaxed_r_type = loongarch_tls_transition (info, r_type, h,
>> input_bfd, r_symndx);
>> + if (relaxed_r_type != r_type)
>> + {
>> +howto = loongarch_elf_rtype_to_howto (input_bfd, relaxed_r_type);
>> +BFD_ASSERT (howto != NULL);
>> +
>> +if (loongarch_tls_relax (input_bfd, input_section, rel, r_type, h,
>> info))
>> + r_type = relaxed_r_type;
>> + }
>> +
>> is_desc = false;
>> is_ie = false;
>> switch (r_type)
>> diff --git a/include/opcode/loongarch.h b/include/opcode/loongarch.h
>> index da936f7945a..32ff4d8a0f1 100644
>> --- a/include/opcode/loongarch.h
>> +++ b/include/opcode/loongarch.h
>> @@ -42,6 +42,12 @@ extern "C"
>> ((value) < (-(1 << ((bits) - 1) << align)) \
>> || (value) > ((((1 << ((bits) - 1)) - 1) << align)))
>>
>> + #define LARCH_LU12I_W 0x14000000
>> + #define LARCH_ORI 0x03800000
>> + #define LARCH_LD_D 0x28c00000
>> + #define LARCH_RD_A0 0x04
>> + #define LARCH_RD_RJ_A0 0x084
>> +
>> typedef uint32_t insn_t;
>>
>> struct loongarch_opcode
>> --
>> 2.43.0
>>
>>
>
next prev parent reply other threads:[~2023-12-29 10:31 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-22 11:42 [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC) Lulu Cai
2023-12-22 11:42 ` [PATCH v5 1/5] LoongArch: Add new relocs and macro for TLSDESC Lulu Cai
2023-12-22 11:42 ` [PATCH v5 2/5] LoongArch: Add support for TLSDESC in ld Lulu Cai
2023-12-28 14:54 ` Tatsuyuki Ishi
2023-12-29 10:24 ` Lulu Cai
2023-12-22 11:42 ` [PATCH v5 3/5] LoongArch: Add tls transition support Lulu Cai
2023-12-28 14:42 ` Tatsuyuki Ishi
2023-12-29 10:31 ` Lulu Cai [this message]
2023-12-22 11:42 ` [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation Lulu Cai
2023-12-28 14:38 ` Tatsuyuki Ishi
2023-12-29 10:36 ` Lulu Cai
2023-12-29 10:45 ` Lulu Cai
2024-01-07 23:00 ` Tatsuyuki Ishi
2024-01-08 0:22 ` Fangrui Song
[not found] ` <DS7PR12MB5765D250CD96B4F6EF6674BACB6B2@DS7PR12MB5765.namprd12.prod.outlook.com>
2024-01-08 6:00 ` Lulu Cai
2024-01-08 7:59 ` Tatsuyuki Ishi
2024-01-27 2:54 ` [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC) Fangrui Song
[not found] ` <DS7PR12MB5765A6FBD6297BAEDB57FF6CCB782@DS7PR12MB5765.namprd12.prod.outlook.com>
2024-01-27 7:26 ` Lulu Cai
2024-01-27 19:18 ` Fangrui Song
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=cdda1f13-aabe-00ec-1ac0-1ba40847d04b@loongson.cn \
--to=cailulu@loongson.cn \
--cc=binutils@sourceware.org \
--cc=chenglulu@loongson.cn \
--cc=hejinyang@loongson.cn \
--cc=i.swmail@xen0n.name \
--cc=ishitatsuyuki@gmail.com \
--cc=liuzhensong@loongson.cn \
--cc=luweining@loongson.cn \
--cc=maskray@google.com \
--cc=mengqinggang@loongson.cn \
--cc=wanglei@loongson.cn \
--cc=xry111@xry111.site \
--cc=xuchenghua@loongson.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).