[v5,1/5] LoongArch: bfd: Add support for tls le relax.

Message ID 20231228033957.108449-2-changjiachen@stu.xupt.edu.cn
State Unresolved
Headers
Series LoongArch tls le model linker relaxation support. |

Checks

Context Check Description
snail/binutils-gdb-check warning Git am fail log

Commit Message

changjiachen Dec. 28, 2023, 3:39 a.m. UTC
  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.
---
 bfd/bfd-in2.h         |  4 +++
 bfd/elfnn-loongarch.c | 75 +++++++++++++++++++++++++++++++++++++++++++
 bfd/elfxx-loongarch.c | 55 ++++++++++++++++++++++++++++---
 bfd/libbfd.h          |  3 ++
 bfd/reloc.c           |  7 ++++
 5 files changed, 139 insertions(+), 5 deletions(-)
  

Comments

Hannes Domani Dec. 29, 2023, 9:53 a.m. UTC | #1
Am Donnerstag, 28. Dezember 2023, 04:41:38 MEZ hat changjiachen <changjiachen@stu.xupt.edu.cn> Folgendes geschrieben:

> 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.
> ---
> bfd/bfd-in2.h        |  4 +++
> bfd/elfnn-loongarch.c | 75 +++++++++++++++++++++++++++++++++++++++++++
> bfd/elfxx-loongarch.c | 55 ++++++++++++++++++++++++++++---
> bfd/libbfd.h          |  3 ++
> bfd/reloc.c          |  7 ++++
> 5 files changed, 139 insertions(+), 5 deletions(-)


When this patch was committed, it also added a bfd/.elfnn-loongarch.c.swp
file, and I doubt this was intentional.


Regards
Hannes
  
changjiachen Dec. 29, 2023, 10:18 a.m. UTC | #2
I am very sorry for my negligence. I will submit another patch to delete the bfd/.elfnn-loongarch.c.wp file. Thank you for your check.--
发自我的网易邮箱
  
Xi Ruoyao Dec. 29, 2023, 12:39 p.m. UTC | #3
On Fri, 2023-12-29 at 09:53 +0000, Hannes Domani wrote:
>  Am Donnerstag, 28. Dezember 2023, 04:41:38 MEZ hat changjiachen <changjiachen@stu.xupt.edu.cn> Folgendes geschrieben:
> 
> > 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.
> > ---
> > bfd/bfd-in2.h        |  4 +++
> > bfd/elfnn-loongarch.c | 75 +++++++++++++++++++++++++++++++++++++++++++
> > bfd/elfxx-loongarch.c | 55 ++++++++++++++++++++++++++++---
> > bfd/libbfd.h          |  3 ++
> > bfd/reloc.c          |  7 ++++
> > 5 files changed, 139 insertions(+), 5 deletions(-)
> 
> 
> When this patch was committed, it also added a bfd/.elfnn-loongarch.c.swp
> file, and I doubt this was intentional.

Hmm interesting: why don't we have *.swp in .gitignore?
  

Patch

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 782845926ea..c522fef5641 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -7473,11 +7473,15 @@  enum bfd_reloc_code_real
   BFD_RELOC_LARCH_TLS_DESC64_HI12,
   BFD_RELOC_LARCH_TLS_DESC_LD,
   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_GD_PCREL20_S2,
   BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,
   BFD_RELOC_UNUSED
 };
+
 typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
 
 reloc_howto_type *bfd_reloc_type_lookup
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index bd448cda453..9a0bcb011ac 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -858,6 +858,7 @@  loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	  break;
 
 	case R_LARCH_TLS_LE_HI20:
+	case R_LARCH_TLS_LE_HI20_R:
 	case R_LARCH_SOP_PUSH_TLS_TPREL:
 	  if (!bfd_link_executable (info))
 	    return false;
@@ -2261,6 +2262,8 @@  perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
     case R_LARCH_GOT64_HI12:
     case R_LARCH_TLS_LE_HI20:
     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_HI12:
     case R_LARCH_TLS_IE_PC_HI20:
@@ -2303,6 +2306,7 @@  perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
       break;
 
     case R_LARCH_RELAX:
+    case R_LARCH_TLS_LE_ADD_R:
       break;
 
     default:
@@ -2483,6 +2487,16 @@  loongarch_reloc_is_fatal (struct bfd_link_info *info,
 	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
    offset = (0x1812348ffff812 & ~0xfff) - (0x11000010000100 & ~0xfff)
 	  = 0x712347ffff000
@@ -3481,6 +3495,13 @@  loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
 	  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:
 	  /* Not support if sym_addr in 2k page edge.
 	     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_LO12:
+	case R_LARCH_TLS_LE_LO12_R:
 	case R_LARCH_TLS_LE64_LO20:
 	case R_LARCH_TLS_LE64_HI12:
 	  BFD_ASSERT (resolved_local && elf_hash_table (info)->tls_sec);
@@ -4089,6 +4111,52 @@  loongarch_relax_delete_bytes (bfd *abfd,
 
   return true;
 }
+/* Relax tls le, mainly relax the process of getting TLS le symbolic addresses.
+
+before relax:				   after relax:
+
+lu12i.w      $r12,%le_hi20_r (sym)	   ==>  (instruction deleted).
+add.d	     $r12,$r12,$r2,%le_add_r (sym) ==>  (instruction deleted).
+st/addi/ld.w $r13,$r12,%le_lo12_r (sym)    ==>  st/addi/ld.w  $r13,$r2,%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.  */
 static bool
@@ -4518,6 +4586,13 @@  loongarch_elf_relax_section (bfd *abfd, asection *sec,
 	      rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
 	    }
 	  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:
 	  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
 	    loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval,
diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
index 4fe8cbff14c..2c40fb02872 100644
--- a/bfd/elfxx-loongarch.c
+++ b/bfd/elfxx-loongarch.c
@@ -1776,9 +1776,56 @@  static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 NULL,					/* adjust_reloc_bits.  */
 	 "desc_call"),				/* larch_reloc_type_name.  */
 
-  LOONGARCH_EMPTY_HOWTO (121),
-  LOONGARCH_EMPTY_HOWTO (122),
-  LOONGARCH_EMPTY_HOWTO (123),
+  LOONGARCH_HOWTO (R_LARCH_TLS_LE_HI20_R,	/* type (121).  */
+	 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_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.  */
   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,
 			     bfd_reloc_code_real_type code)
 {
-  /*
   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
-  */
 
   /* Fast search for new reloc types.  */
   if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX)
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 8dab44110a6..82ffd773513 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -3612,6 +3612,9 @@  static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_LARCH_TLS_DESC64_HI12",
   "BFD_RELOC_LARCH_TLS_DESC_LD",
   "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_GD_PCREL20_S2",
   "BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 6fd0f1fb547..1030bc37647 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -8324,6 +8324,13 @@  ENUMX
 ENUMX
   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
   BFD_RELOC_LARCH_TLS_LD_PCREL20_S2
 ENUMX