From: Lulu Cai <cailulu@loongson.cn>
To: binutils@sourceware.org
Cc: 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, Lulu Cai <cailulu@loongson.cn>
Subject: [PATCH 1/2] LoongArch: Fix incorrect type transition under extreme cmodel
Date: Sat, 27 Jan 2024 21:12:10 +0800 [thread overview]
Message-ID: <20240127131211.795952-1-cailulu@loongson.cn> (raw)
This patch mainly fixes the bug of tls type transition when -mcmodel=extreme.
Because the first two instructions of normal and extreme use the same
relocation, this will cause an incorrect type transition when -mcmodel=extreme,
similar to:
pcalau12i t0, %ie_pc_hi20(x)
li.d t1, %ie_pc_lo12(x)
lu32i.d t1, %ie64_pc_lo20(x)
lu52i.d t1, t1, %ie64_pc_hi12(x)
ldx.d t0, t0, t1
Transition to
lu12i.w t0, %le_hi20(x)
ori t1, t1, %le_lo12(x)
lu32i.d t1, %ie64_pc_lo20(x)
lu52i.d t1, t1, %ie64_pc_hi12(x)
ldx.d t0, t0, t1
In order to avoid this situation, we only do type transition for normal, and
each relocation that can be type transition will be accompanied by an
R_LARCH_RELAX, and will not issue R_LARCH_RELAX for TLS instruction sequences
of other code models.
---
bfd/elfnn-loongarch.c | 67 +++++++++++++++++++++++----------------
gas/config/tc-loongarch.c | 19 +++++++++--
2 files changed, 56 insertions(+), 30 deletions(-)
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 1895699af06..d51841e7973 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -145,14 +145,12 @@ 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 \
+#define IS_LOONGARCH_TLS_TRANS_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 \
+ || (R_TYPE) == R_LARCH_TLS_IE_PC_HI20 \
|| (R_TYPE) == R_LARCH_TLS_IE_PC_LO12)
/* Generate a PLT header. */
@@ -642,15 +640,20 @@ loongarch_reloc_got_type (unsigned int r_type)
/* 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)
+loongarch_can_trans_tls (bfd *input_bfd,
+ struct bfd_link_info *info,
+ struct elf_link_hash_entry *h,
+ const Elf_Internal_Rela *rel,
+ unsigned int r_type)
{
char symbol_tls_type;
unsigned int reloc_got_type;
+ unsigned int r_symndx = ELFNN_R_SYM (rel->r_info);
- if (! (IS_LOONGARCH_TLS_DESC_RELOC (r_type)
- || IS_LOONGARCH_TLS_IE_RELOC (r_type)))
+ /* Only TLS DESC/IE in normal code mode will perform type
+ transition. */
+ if (! (IS_LOONGARCH_TLS_TRANS_RELOC (r_type)
+ && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX))
return false;
symbol_tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
@@ -707,11 +710,13 @@ loongarch_tls_transition_without_check (struct bfd_link_info *info,
}
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)
+loongarch_tls_transition (bfd *input_bfd,
+ struct bfd_link_info *info,
+ struct elf_link_hash_entry *h,
+ const Elf_Internal_Rela *rel,
+ unsigned int r_type)
{
- if (! loongarch_can_relax_tls (info, r_type, h, input_bfd,r_symndx))
+ if (! loongarch_can_trans_tls (input_bfd, info, h, rel, r_type))
return r_type;
return loongarch_tls_transition_without_check (info, r_type, h);
@@ -818,7 +823,10 @@ 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);
+ /* Type transitions are only possible with relocations accompanied
+ by R_LARCH_RELAX. */
+ if (rel + 1 != relocs + sec->reloc_count)
+ r_type = loongarch_tls_transition (abfd, info, h, rel, r_type);
switch (r_type)
{
case R_LARCH_GOT_PC_HI20:
@@ -2536,7 +2544,7 @@ loongarch_reloc_is_fatal (struct bfd_link_info *info,
/* Transition instruction sequence to relax instruction sequence. */
static bool
-loongarch_tls_relax (bfd *abfd, asection *sec, Elf_Internal_Rela *rel,
+loongarch_tls_perform_trans (bfd *abfd, asection *sec, Elf_Internal_Rela *rel,
int r_type, struct elf_link_hash_entry *h,
struct bfd_link_info *info)
{
@@ -2657,7 +2665,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;
+ unsigned int trans_r_type = r_type;
bool resolved_local, resolved_dynly, resolved_to_const;
char tls_type;
bfd_vma relocation, off, ie_off, desc_off;
@@ -2789,14 +2797,17 @@ 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)
+ if (rel + 1 != relend)
+ trans_r_type = loongarch_tls_transition (input_bfd, info, h,
+ rel, r_type);
+ if (trans_r_type != r_type)
{
- howto = loongarch_elf_rtype_to_howto (input_bfd, relaxed_r_type);
+ howto = loongarch_elf_rtype_to_howto (input_bfd, trans_r_type);
BFD_ASSERT (howto != NULL);
- if (loongarch_tls_relax (input_bfd, input_section, rel, r_type, h, info))
- r_type = relaxed_r_type;
+ if (loongarch_tls_perform_trans (input_bfd, input_section,
+ rel, r_type, h, info))
+ r_type = trans_r_type;
}
is_desc = false;
@@ -4551,7 +4562,8 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
|| R_LARCH_TLS_GD_PC_HI20 == r_type
|| R_LARCH_TLS_DESC_PC_HI20 == r_type)
{
- if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
+ if (i + 1 != sec->reloc_count
+ && loongarch_can_trans_tls (abfd, info, h, rel, r_type))
continue;
else
{
@@ -4595,7 +4607,8 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
|| R_LARCH_TLS_GD_PC_HI20 == r_type
|| R_LARCH_TLS_DESC_PC_HI20 == r_type)
{
- if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
+ if (i + 1 != sec->reloc_count
+ && loongarch_can_trans_tls (abfd, info, h, rel, r_type))
continue;
else
{
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index e0aff36bbbb..af4426bff94 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -724,8 +724,12 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
}
/* Only one register macros (used in normal code model)
- emit R_LARCH_RELAX. */
+ emit R_LARCH_RELAX.
+ LARCH_opts.ase_labs and LARCH_opts.ase_gabs are used
+ to generate the code model of absolute addresses, and
+ we do not relax this code model. */
if (LARCH_opts.relax && (ip->expand_from_macro & 1)
+ && ! (LARCH_opts.ase_labs | LARCH_opts.ase_gabs)
&& (BFD_RELOC_LARCH_PCALA_HI20 == reloc_type
|| BFD_RELOC_LARCH_PCALA_LO12 == reloc_type
|| BFD_RELOC_LARCH_GOT_PC_HI20 == reloc_type
@@ -733,7 +737,11 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
|| BFD_RELOC_LARCH_TLS_LD_PC_HI20 == reloc_type
|| BFD_RELOC_LARCH_TLS_GD_PC_HI20 == reloc_type
|| BFD_RELOC_LARCH_TLS_DESC_PC_HI20 == reloc_type
- || BFD_RELOC_LARCH_TLS_DESC_PC_LO12 == reloc_type))
+ || BFD_RELOC_LARCH_TLS_DESC_PC_LO12 == reloc_type
+ || BFD_RELOC_LARCH_TLS_DESC_LD == reloc_type
+ || BFD_RELOC_LARCH_TLS_DESC_CALL == reloc_type
+ || BFD_RELOC_LARCH_TLS_IE_PC_HI20 == reloc_type
+ || BFD_RELOC_LARCH_TLS_IE_PC_LO12 == reloc_type))
{
ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
ip->reloc_info[ip->reloc_num].value = const_0;
@@ -1088,7 +1096,12 @@ append_fixp_and_insn (struct loongarch_cl_insn *ip)
|| BFD_RELOC_LARCH_TLS_LE_ADD_R == reloc_info[0].type
|| BFD_RELOC_LARCH_TLS_LD_PC_HI20 == reloc_info[0].type
|| BFD_RELOC_LARCH_TLS_GD_PC_HI20 == reloc_info[0].type
- || BFD_RELOC_LARCH_TLS_DESC_PC_HI20 == reloc_info[0].type))
+ || BFD_RELOC_LARCH_TLS_DESC_PC_HI20 == reloc_info[0].type
+ || BFD_RELOC_LARCH_TLS_DESC_PC_LO12 == reloc_info[0].type
+ || BFD_RELOC_LARCH_TLS_DESC_LD == reloc_info[0].type
+ || BFD_RELOC_LARCH_TLS_DESC_CALL == reloc_info[0].type
+ || BFD_RELOC_LARCH_TLS_IE_PC_HI20 == reloc_info[0].type
+ || BFD_RELOC_LARCH_TLS_IE_PC_LO12 == reloc_info[0].type))
{
frag_wane (frag_now);
frag_new (0);
--
2.36.0
next reply other threads:[~2024-01-27 13:12 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-27 13:12 Lulu Cai [this message]
2024-01-27 13:12 ` [PATCH 2/2] LoongArch: update test cases about TLS Lulu Cai
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=20240127131211.795952-1-cailulu@loongson.cn \
--to=cailulu@loongson.cn \
--cc=binutils@sourceware.org \
--cc=chenglulu@loongson.cn \
--cc=hejinyang@loongson.cn \
--cc=i.swmail@xen0n.name \
--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).