public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
@ 2022-07-18  8:43 liuzhensong
  2022-07-18  8:43 ` [PATCH 2/5 v1] LoongArch:opcodes: " liuzhensong
                   ` (5 more replies)
  0 siblings, 6 replies; 24+ messages in thread
From: liuzhensong @ 2022-07-18  8:43 UTC (permalink / raw)
  To: binutils; +Cc: xuchenghua, mengqinggang, liuzhensong

This is the v1 version of patches to support new relocs for LoongArch.

The new reloc types docnments are on:
https://github.com/loongson/LoongArch-Documentation/pull/57/files

The testsuite status:

                === binutils Summary ===                                                                                                                                                                           
                                                                                 
# of expected passes            241                                              
# of unsupported tests          6

                === gas Summary ===                                                                                                                                                                                
                                                                                 
# of expected passes            270                                              
# of unsupported tests          7

                === ld Summary ===                                                                                                                                                                                 
                                                                                 
# of expected passes            1457                                             
# of expected failures          11                                               
# of untested testcases         1                                                
# of unsupported tests          154


  Add new reloc types support, the new relocate type
  definition depends which operation needs of linker.


---
 bfd/bfd-in2.h           |   36 ++
 bfd/elfnn-loongarch.c   | 1194 ++++++++++++++++++++++------------
 bfd/elfxx-loongarch.c   | 1354 +++++++++++++++++++++++++++++----------
 bfd/elfxx-loongarch.h   |    4 +
 bfd/libbfd.h            |   36 ++
 bfd/reloc.c             |   79 +++
 include/elf/loongarch.h |  142 +++-
 7 files changed, 2095 insertions(+), 750 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 4e1182e93d4..a71b3e82057 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6274,6 +6274,42 @@ assembler and not (currently) written to any object files.  */
   BFD_RELOC_LARCH_SUB24,
   BFD_RELOC_LARCH_SUB32,
   BFD_RELOC_LARCH_SUB64,
+  BFD_RELOC_LARCH_B16,
+  BFD_RELOC_LARCH_B21,
+  BFD_RELOC_LARCH_B26,
+  BFD_RELOC_LARCH_ABS_HI20,
+  BFD_RELOC_LARCH_ABS_LO12,
+  BFD_RELOC_LARCH_ABS64_LO20,
+  BFD_RELOC_LARCH_ABS64_HI12,
+  BFD_RELOC_LARCH_PCALA_HI20,
+  BFD_RELOC_LARCH_PCALA_LO12,
+  BFD_RELOC_LARCH_PCALA64_LO20,
+  BFD_RELOC_LARCH_PCALA64_HI12,
+  BFD_RELOC_LARCH_GOT_PC_HI20,
+  BFD_RELOC_LARCH_GOT_PC_LO12,
+  BFD_RELOC_LARCH_GOT64_PC_LO20,
+  BFD_RELOC_LARCH_GOT64_PC_HI12,
+  BFD_RELOC_LARCH_GOT64_HI20,
+  BFD_RELOC_LARCH_GOT64_LO12,
+  BFD_RELOC_LARCH_GOT64_LO20,
+  BFD_RELOC_LARCH_GOT64_HI12,
+  BFD_RELOC_LARCH_TLS_LE_HI20,
+  BFD_RELOC_LARCH_TLS_LE_LO12,
+  BFD_RELOC_LARCH_TLS_LE64_LO20,
+  BFD_RELOC_LARCH_TLS_LE64_HI12,
+  BFD_RELOC_LARCH_TLS_IE_PC_HI20,
+  BFD_RELOC_LARCH_TLS_IE_PC_LO12,
+  BFD_RELOC_LARCH_TLS_IE64_PC_LO20,
+  BFD_RELOC_LARCH_TLS_IE64_PC_HI12,
+  BFD_RELOC_LARCH_TLS_IE64_HI20,
+  BFD_RELOC_LARCH_TLS_IE64_LO12,
+  BFD_RELOC_LARCH_TLS_IE64_LO20,
+  BFD_RELOC_LARCH_TLS_IE64_HI12,
+  BFD_RELOC_LARCH_TLS_LD_PC_HI20,
+  BFD_RELOC_LARCH_TLS_LD64_HI20,
+  BFD_RELOC_LARCH_TLS_GD_PC_HI20,
+  BFD_RELOC_LARCH_TLS_GD64_HI20,
+  BFD_RELOC_LARCH_RELAX,
   BFD_RELOC_UNUSED };
 
 typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 5b44901b9e0..4eeaeb44eff 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -122,14 +122,16 @@ struct loongarch_elf_link_hash_table
 
 #define elf_backend_plt_readonly 1
 
-#define elf_backend_want_plt_sym 0
+#define elf_backend_want_plt_sym 1
 #define elf_backend_plt_alignment 4
 #define elf_backend_can_gc_sections 1
+#define elf_backend_can_refcount 1
 #define elf_backend_want_got_sym 1
 
 #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 1)
 
 #define elf_backend_want_dynrelro 1
+#define elf_backend_rela_normal 1
 
 /* Generate a PLT header.  */
 
@@ -607,9 +609,6 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *isym = NULL;
 
-      int need_dynreloc;
-      int only_need_pcrel;
-
       r_symndx = ELFNN_R_SYM (rel->r_info);
       r_type = ELFNN_R_TYPE (rel->r_info);
 
@@ -622,7 +621,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       if (r_symndx < symtab_hdr->sh_info)
 	{
 	  /* A local symbol.  */
-	  isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, r_symndx);
+	  isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx);
 	  if (isym == NULL)
 	    return false;
 
@@ -655,17 +654,20 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	  if (htab->elf.dynobj == NULL)
 	    htab->elf.dynobj = abfd;
 
+	  /* Create 'irelifunc' in PIC object.  */
+	  if (bfd_link_pic (info)
+	      && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
+	    return false;
+	    /* If '.plt' not represent, create '.iplt' to deal with ifunc.  */
+	  else if (!htab->elf.splt
+	      && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
+	    return false;
 	  /* Create the ifunc sections, iplt and ipltgot, for static
 	     executables.  */
 	  if ((r_type == R_LARCH_64 || r_type == R_LARCH_32)
 	      && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
 	    return false;
 
-	  if (!htab->elf.splt
-	      && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
-	    /* If '.plt' not represent, create '.iplt' to deal with ifunc.  */
-	    return false;
-
 	  if (h->plt.refcount < 0)
 	    h->plt.refcount = 0;
 	  h->plt.refcount++;
@@ -674,17 +676,27 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	  elf_tdata (info->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_ifunc;
 	}
 
-      need_dynreloc = 0;
-      only_need_pcrel = 0;
+      int need_dynreloc = 0;
+      int only_need_pcrel = 0;
+
       switch (r_type)
 	{
+	case R_LARCH_GOT_PC_HI20:
+	case R_LARCH_GOT64_HI20:
 	case R_LARCH_SOP_PUSH_GPREL:
+	  /* For la.global.  */
+	  if (h)
+	    h->pointer_equality_needed = 1;
 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
 							   r_symndx,
 							   GOT_NORMAL))
 	    return false;
 	  break;
 
+	case R_LARCH_TLS_LD_PC_HI20:
+	case R_LARCH_TLS_LD64_HI20:
+	case R_LARCH_TLS_GD_PC_HI20:
+	case R_LARCH_TLS_GD64_HI20:
 	case R_LARCH_SOP_PUSH_TLS_GD:
 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
 							   r_symndx,
@@ -692,6 +704,8 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    return false;
 	  break;
 
+	case R_LARCH_TLS_IE_PC_HI20:
+	case R_LARCH_TLS_IE64_HI20:
 	case R_LARCH_SOP_PUSH_TLS_GOT:
 	  if (bfd_link_pic (info))
 	    /* May fail for lazy-bind.  */
@@ -703,6 +717,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    return false;
 	  break;
 
+	case R_LARCH_TLS_LE_HI20:
 	case R_LARCH_SOP_PUSH_TLS_TPREL:
 	  if (!bfd_link_executable (info))
 	    return false;
@@ -715,6 +730,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    return false;
 	  break;
 
+	case R_LARCH_ABS_HI20:
 	case R_LARCH_SOP_PUSH_ABSOLUTE:
 	  if (h != NULL)
 	    /* If this reloc is in a read-only section, we might
@@ -726,16 +742,45 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    h->non_got_ref = 1;
 	  break;
 
-	case R_LARCH_SOP_PUSH_PCREL:
+	case R_LARCH_PCALA_HI20:
 	  if (h != NULL)
 	    {
 	      h->non_got_ref = 1;
+	      h->pointer_equality_needed = 1;
+	    }
+
+	  break;
+
+	case R_LARCH_B21:
+	case R_LARCH_B16:
+	case R_LARCH_B26:
+	  if (h != NULL)
+	    {
+	      h->needs_plt = 1;
+	      if (!bfd_link_pic (info))
+		h->non_got_ref = 1;
+
+	      /* We try to create PLT stub for all non-local function.  */
+	      if (h->plt.refcount < 0)
+		h->plt.refcount = 0;
+	      h->plt.refcount++;
+	    }
+
+	  break;
+
+	case R_LARCH_SOP_PUSH_PCREL:
+	  if (h != NULL)
+	    {
+	      if (!bfd_link_pic (info))
+		h->non_got_ref = 1;
 
 	      /* We try to create PLT stub for all non-local function.  */
 	      if (h->plt.refcount < 0)
 		h->plt.refcount = 0;
 	      h->plt.refcount++;
+	      h->pointer_equality_needed = 1;
 	    }
+
 	  break;
 
 	case R_LARCH_SOP_PUSH_PLT_PCREL:
@@ -762,6 +807,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	case R_LARCH_JUMP_SLOT:
 	case R_LARCH_32:
 	case R_LARCH_64:
+
 	  need_dynreloc = 1;
 
 	  /* If resolved symbol is defined in this object,
@@ -774,9 +820,6 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	     Thus, only under pde, it needs pcrel only.  We discard it.  */
 	  only_need_pcrel = bfd_link_pde (info);
 
-	  if (h != NULL)
-	    h->non_got_ref = 1;
-
 	  if (h != NULL
 	      && (!bfd_link_pic (info)
 		  || h->type == STT_GNU_IFUNC))
@@ -899,9 +942,7 @@ loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 				     struct elf_link_hash_entry *h)
 {
   struct loongarch_elf_link_hash_table *htab;
-  struct loongarch_elf_link_hash_entry *eh;
   bfd *dynobj;
-  asection *s, *srel;
 
   htab = loongarch_elf_hash_table (info);
   BFD_ASSERT (htab != NULL);
@@ -951,73 +992,9 @@ loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       return true;
     }
 
-  /* This is a reference to a symbol defined by a dynamic object which
-     is not a function.  */
-
-  /* If we are creating a shared library, we must presume that the
-     only references to the symbol are via the global offset table.
-     For such cases we need not do anything here; the relocations will
-     be handled correctly by relocate_section.  */
-  if (bfd_link_dll (info))
-    return true;
-
-  /* If there are no references to this symbol that do not use the
-     GOT, we don't need to generate a copy reloc.  */
-  if (!h->non_got_ref)
-    return true;
-
-  /* If -z nocopyreloc was given, we won't generate them either.  */
-  if (info->nocopyreloc)
-    {
-      h->non_got_ref = 0;
-      return true;
-    }
-
-  /* If we don't find any dynamic relocs in read-only sections, then
-     we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
-  if (!readonly_dynrelocs (h))
-    {
-      h->non_got_ref = 0;
-      return true;
-    }
-
-  /* We must allocate the symbol in our .dynbss section, which will
-     become part of the .bss section of the executable.  There will be
-     an entry for this symbol in the .dynsym section.  The dynamic
-     object will contain position independent code, so all references
-     from the dynamic object to this symbol will go through the global
-     offset table.  The dynamic linker will use the .dynsym entry to
-     determine the address it must put in the global offset table, so
-     both the dynamic object and the regular object will refer to the
-     same memory location for the variable.  */
-
-  /* We must generate a R_LARCH_COPY reloc to tell the dynamic linker
-     to copy the initial value out of the dynamic object and into the
-     runtime process image.  We need to remember the offset into the
-     .rel.bss section we are going to use.  */
-  eh = (struct loongarch_elf_link_hash_entry *) h;
-  if (eh->tls_type & ~GOT_NORMAL)
-    {
-      s = htab->sdyntdata;
-      srel = htab->elf.srelbss;
-    }
-  else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
-    {
-      s = htab->elf.sdynrelro;
-      srel = htab->elf.sreldynrelro;
-    }
-  else
-    {
-      s = htab->elf.sdynbss;
-      srel = htab->elf.srelbss;
-    }
-  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
-    {
-      srel->size += sizeof (ElfNN_External_Rela);
-      h->needs_copy = 1;
-    }
-
-  return _bfd_elf_adjust_dynamic_copy (info, h, s);
+  /* R_LARCH_COPY is not adept glibc, not to generate.  */
+  /* Can not print anything, because make check ld.  */
+  return true;
 }
 
 /* Allocate space in .plt, .got and associated reloc sections for
@@ -1039,6 +1016,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
   info = (struct bfd_link_info *) inf;
   htab = loongarch_elf_hash_table (info);
+  bool dyn = htab->elf.dynamic_sections_created;
   BFD_ASSERT (htab != NULL);
 
   do
@@ -1052,9 +1030,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
       if (htab->elf.splt)
 	{
-	  if (h->dynindx == -1 && !h->forced_local
-	      && !bfd_elf_link_record_dynamic_symbol (info, h))
-	    return false;
+	  if (h->dynindx == -1 && !h->forced_local && dyn
+	      && h->root.type == bfd_link_hash_undefweak)
+	    {
+	      if (!bfd_elf_link_record_dynamic_symbol (info, h))
+		return false;
+	    }
 
 	  if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)
 	      && h->type != STT_GNU_IFUNC)
@@ -1090,7 +1071,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 	 location in the .plt.  This is required to make function
 	 pointers compare as equal between the normal executable and
 	 the shared library.  */
-      if (!bfd_link_pic(info)
+      if (!bfd_link_pic (info)
 	  && !h->def_regular)
 	{
 	  h->root.u.def.section = plt;
@@ -1107,51 +1088,68 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   if (0 < h->got.refcount)
     {
       asection *s;
-      bool dyn;
       int tls_type = loongarch_elf_hash_entry (h)->tls_type;
 
       /* Make sure this symbol is output as a dynamic symbol.
 	 Undefined weak syms won't yet be marked as dynamic.  */
-      if (h->dynindx == -1 && !h->forced_local)
+      if (h->dynindx == -1 && !h->forced_local && dyn
+	  && h->root.type == bfd_link_hash_undefweak)
 	{
-	  if (SYMBOL_REFERENCES_LOCAL (info, h)
-	      && (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-	      && h->start_stop)
-	    {
-	      /* The pr21964-4. do nothing.  */
-	    }
-	  else
-	    {
-	      if( !bfd_elf_link_record_dynamic_symbol (info, h))
-		return false;
-	    }
+	  if (!bfd_elf_link_record_dynamic_symbol (info, h))
+	    return false;
 	}
 
       s = htab->elf.sgot;
       h->got.offset = s->size;
-      dyn = htab->elf.dynamic_sections_created;
       if (tls_type & (GOT_TLS_GD | GOT_TLS_IE))
 	{
 	  /* TLS_GD needs two dynamic relocs and two GOT slots.  */
 	  if (tls_type & GOT_TLS_GD)
 	    {
 	      s->size += 2 * GOT_ENTRY_SIZE;
-	      htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
+	      if (bfd_link_executable (info))
+		{
+		  /* Link exe and not defined local.  */
+		  if (!SYMBOL_REFERENCES_LOCAL (info, h))
+		    htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
+		}
+	      else
+		{
+		  if (SYMBOL_REFERENCES_LOCAL (info, h))
+		    htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
+		  else
+		    htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
+		}
 	    }
 
 	  /* TLS_IE needs one dynamic reloc and one GOT slot.  */
 	  if (tls_type & GOT_TLS_IE)
 	    {
 	      s->size += GOT_ENTRY_SIZE;
-	      htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
+
+	      if (bfd_link_executable (info))
+		{
+		  /* Link exe and not defined local.  */
+		  if (!SYMBOL_REFERENCES_LOCAL (info, h))
+		    htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
+		}
+	      else
+		{
+		  htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
+		}
 	    }
 	}
       else
 	{
 	  s->size += GOT_ENTRY_SIZE;
-	  if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)
-	       && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
-	      || h->type == STT_GNU_IFUNC)
+	  if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+	       || h->root.type != bfd_link_hash_undefweak)
+	      && (bfd_link_pic (info)
+		  || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info),
+						      h))
+	      && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+	      /* Undefined weak symbol in static PIE resolves to 0 without
+		 any dynamic relocations.  */
 	    htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
 	}
     }
@@ -1161,7 +1159,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   if (h->dyn_relocs == NULL)
     return true;
 
-  if (SYMBOL_REFERENCES_LOCAL (info, h))
+  /* Extra dynamic relocate,
+   * R_LARCH_64
+   * R_LARCH_TLS_DTPRELNN
+   * R_LARCH_JUMP_SLOT
+   * R_LARCH_NN.  */
+
+  if (SYMBOL_CALLS_LOCAL (info, h))
     {
       struct elf_dyn_relocs **pp;
 
@@ -1178,13 +1182,20 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
   if (h->root.type == bfd_link_hash_undefweak)
     {
-      if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+      if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)
+	  || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+	  || (!bfd_link_pic (info) && h->non_got_ref))
 	h->dyn_relocs = NULL;
-      else if (h->dynindx == -1 && !h->forced_local
-	       /* Make sure this symbol is output as a dynamic symbol.
-		  Undefined weak syms won't yet be marked as dynamic.  */
-	       && !bfd_elf_link_record_dynamic_symbol (info, h))
-	return false;
+      else if (h->dynindx == -1 && !h->forced_local)
+	{
+	  /* Make sure this symbol is output as a dynamic symbol.
+	     Undefined weak syms won't yet be marked as dynamic.  */
+	  if (!bfd_elf_link_record_dynamic_symbol (info, h))
+	    return false;
+
+	  if (h->dynindx == -1)
+	    h->dyn_relocs = NULL;
+	}
     }
 
   for (p = h->dyn_relocs; p != NULL; p = p->next)
@@ -1200,8 +1211,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
    ifunc dynamic relocs.  */
 
 static bool
-elfNN_loongarch_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
-					  void *inf)
+elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 {
   struct bfd_link_info *info;
   /* An example of a bfd_link_hash_indirect symbol is versioned
@@ -1223,14 +1233,14 @@ elfNN_loongarch_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
 
   /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
      here if it is defined and referenced in a non-shared object.  */
-  if (h->type == STT_GNU_IFUNC
-      && h->def_regular)
+  if (h->type == STT_GNU_IFUNC && h->def_regular)
     return _bfd_elf_allocate_ifunc_dyn_relocs (info, h,
 					       &h->dyn_relocs,
 					       PLT_ENTRY_SIZE,
 					       PLT_HEADER_SIZE,
 					       GOT_ENTRY_SIZE,
 					       false);
+
   return true;
 }
 
@@ -1238,7 +1248,7 @@ elfNN_loongarch_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
    ifunc dynamic relocs.  */
 
 static bool
-elfNN_loongarch_allocate_local_dynrelocs (void **slot, void *inf)
+elfNN_allocate_local_ifunc_dynrelocs (void **slot, void *inf)
 {
   struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
 
@@ -1249,7 +1259,7 @@ elfNN_loongarch_allocate_local_dynrelocs (void **slot, void *inf)
       || h->root.type != bfd_link_hash_defined)
     abort ();
 
-  return elfNN_loongarch_allocate_ifunc_dynrelocs (h, inf);
+  return elfNN_allocate_ifunc_dynrelocs (h, inf);
 }
 
 /* Set DF_TEXTREL if we find any dynamic relocs that apply to
@@ -1367,16 +1377,21 @@ loongarch_elf_size_dynamic_sections (bfd *output_bfd,
 	  if (0 < *local_got)
 	    {
 	      *local_got = s->size;
-	      s->size += GOT_ENTRY_SIZE;
 
+	      /* TLS gd use two got.  */
 	      if (*local_tls_type & GOT_TLS_GD)
+		s->size += GOT_ENTRY_SIZE * 2;
+	      else
+		/* Normal got, tls ie/ld use one got.  */
 		s->size += GOT_ENTRY_SIZE;
 
-	      /* If R_LARCH_RELATIVE.  */
-	      if (bfd_link_pic (info)
-		  /* Or R_LARCH_TLS_DTPRELNN or R_LARCH_TLS_TPRELNN.  */
-		  || (*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE)))
-		srel->size += sizeof (ElfNN_External_Rela);
+	      if (bfd_link_executable (info)
+		  && (*local_tls_type & (GOT_TLS_GD| GOT_TLS_IE)))
+		;/* Do nothing.  */
+	      else
+		{
+		  srel->size += sizeof (ElfNN_External_Rela);
+		}
 	    }
 	  else
 	    *local_got = MINUS_ONE;
@@ -1389,11 +1404,11 @@ loongarch_elf_size_dynamic_sections (bfd *output_bfd,
 
   /* Allocate global ifunc sym .plt and .got entries, and space for global
      ifunc sym dynamic relocs.  */
-  elf_link_hash_traverse (&htab->elf, elfNN_loongarch_allocate_ifunc_dynrelocs, info);
+  elf_link_hash_traverse (&htab->elf, elfNN_allocate_ifunc_dynrelocs, info);
 
   /* Allocate .plt and .got entries, and space for local ifunc symbols.  */
   htab_traverse (htab->loc_hash_table,
-		 (void *) elfNN_loongarch_allocate_local_dynrelocs, info);
+		 (void *) elfNN_allocate_local_ifunc_dynrelocs, info);
 
   /* Don't allocate .got.plt section if there are no PLT.  */
   if (htab->elf.sgotplt && htab->elf.sgotplt->size == GOTPLT_HEADER_SIZE
@@ -1542,10 +1557,13 @@ loongarch_top (int64_t *val)
 static void
 loongarch_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
 {
+  BFD_ASSERT (s && s->contents);
   const struct elf_backend_data *bed;
   bfd_byte *loc;
 
   bed = get_elf_backend_data (abfd);
+  if (!(s->size > s->reloc_count * bed->s->sizeof_rela))
+    BFD_ASSERT (s->size > s->reloc_count * bed->s->sizeof_rela);
   loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela);
   bed->s->swap_reloca_out (abfd, rel, loc);
 }
@@ -1594,19 +1612,15 @@ loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela *rel,
   return bfd_reloc_ok;
 }
 
-/* Emplace a static relocation.  */
-
 static bfd_reloc_status_type
 perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
 		    reloc_howto_type *howto, bfd_vma value,
 		    bfd *input_bfd, bfd_byte *contents)
 {
-  uint32_t insn1;
   int64_t opr1, opr2, opr3;
   bfd_reloc_status_type r = bfd_reloc_ok;
   int bits = bfd_get_reloc_size (howto) * 8;
 
-
   switch (ELFNN_R_TYPE (rel->r_info))
     {
     case R_LARCH_SOP_PUSH_PCREL:
@@ -1679,6 +1693,8 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
     case R_LARCH_SOP_POP_32_S_10_12:
     case R_LARCH_SOP_POP_32_S_10_16:
     case R_LARCH_SOP_POP_32_S_10_16_S2:
+    case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
+    case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
     case R_LARCH_SOP_POP_32_S_5_20:
     case R_LARCH_SOP_POP_32_U_10_12:
     case R_LARCH_SOP_POP_32_U:
@@ -1694,67 +1710,6 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
 					    contents, (bfd_vma)opr1);
       break;
 
-    case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
-	{
-	  r = loongarch_pop (&opr1);
-	  if (r != bfd_reloc_ok)
-	    break;
-
-	  if ((opr1 & 0x3) != 0)
-	    {
-	      r = bfd_reloc_overflow;
-	      break;
-	    }
-
-	  uint32_t imm = opr1 >> howto->rightshift;
-	  if ((imm & (~0xfffffU)) && ((imm & (~0xfffffU)) != (~0xfffffU)))
-	    {
-	      r = bfd_reloc_overflow;
-	      break;
-	    }
-	  r = loongarch_check_offset (rel, input_section);
-	  if (r != bfd_reloc_ok)
-	    break;
-
-	  insn1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
-	  insn1 = (insn1 & howto->src_mask)
-	    | ((imm & 0xffffU) << 10)
-	    | ((imm & 0x1f0000U) >> 16);
-	  bfd_put (bits, input_bfd, insn1, contents + rel->r_offset);
-	  break;
-	}
-
-    case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
-      {
-	r = loongarch_pop (&opr1);
-	if (r != bfd_reloc_ok)
-	  break;
-
-	if ((opr1 & 0x3) != 0)
-	  {
-	    r = bfd_reloc_overflow;
-	    break;
-	  }
-
-	uint32_t imm = opr1 >> howto->rightshift;
-	if ((imm & (~0x1ffffffU)) && (imm & (~0x1ffffffU)) != (~0x1ffffffU))
-	  {
-	    r = bfd_reloc_overflow;
-	    break;
-	  }
-
-	r = loongarch_check_offset (rel, input_section);
-	if (r != bfd_reloc_ok)
-	  break;
-
-	insn1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
-	insn1 = ((insn1 & howto->src_mask)
-		 | ((imm & 0xffffU) << 10)
-		 | ((imm & 0x3ff0000U) >> 16));
-	bfd_put (bits, input_bfd, insn1, contents + rel->r_offset);
-	break;
-      }
-
     case R_LARCH_TLS_DTPREL32:
     case R_LARCH_32:
     case R_LARCH_TLS_DTPREL64:
@@ -1792,6 +1747,55 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
       bfd_put (bits, input_bfd, opr1 - value, contents + rel->r_offset);
       break;
 
+    /* New reloc type.
+       R_LARCH_B16 ~ R_LARCH_TLS_GD64_HI20.  */
+    case R_LARCH_B16:
+    case R_LARCH_B21:
+    case R_LARCH_B26:
+    case R_LARCH_ABS_HI20:
+    case R_LARCH_ABS_LO12:
+    case R_LARCH_ABS64_LO20:
+    case R_LARCH_ABS64_HI12:
+    case R_LARCH_PCALA_HI20:
+    case R_LARCH_PCALA_LO12:
+    case R_LARCH_PCALA64_LO20:
+    case R_LARCH_PCALA64_HI12:
+    case R_LARCH_GOT_PC_HI20:
+    case R_LARCH_GOT_PC_LO12:
+    case R_LARCH_GOT64_PC_LO20:
+    case R_LARCH_GOT64_PC_HI12:
+    case R_LARCH_GOT64_HI20:
+    case R_LARCH_GOT64_LO12:
+    case R_LARCH_GOT64_LO20:
+    case R_LARCH_GOT64_HI12:
+    case R_LARCH_TLS_LE_HI20:
+    case R_LARCH_TLS_LE_LO12:
+    case R_LARCH_TLS_LE64_LO20:
+    case R_LARCH_TLS_LE64_HI12:
+    case R_LARCH_TLS_IE_PC_HI20:
+    case R_LARCH_TLS_IE_PC_LO12:
+    case R_LARCH_TLS_IE64_PC_LO20:
+    case R_LARCH_TLS_IE64_PC_HI12:
+    case R_LARCH_TLS_IE64_HI20:
+    case R_LARCH_TLS_IE64_LO12:
+    case R_LARCH_TLS_IE64_LO20:
+    case R_LARCH_TLS_IE64_HI12:
+    case R_LARCH_TLS_LD_PC_HI20:
+    case R_LARCH_TLS_LD64_HI20:
+    case R_LARCH_TLS_GD_PC_HI20:
+    case R_LARCH_TLS_GD64_HI20:
+      r = loongarch_check_offset (rel, input_section);
+      if (r != bfd_reloc_ok)
+	break;
+
+      r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
+					    howto, input_bfd,
+					    contents, value);
+      break;
+
+    case R_LARCH_RELAX:
+      break;
+
     default:
       r = bfd_reloc_notsupported;
     }
@@ -1900,7 +1904,6 @@ loongarch_dump_reloc_record (void (*p) (const char *fmt, ...))
      "-- Record dump end --\n\n");
 }
 
-
 static bool
 loongarch_reloc_is_fatal (struct bfd_link_info *info,
 			  bfd *input_bfd,
@@ -1945,8 +1948,27 @@ loongarch_reloc_is_fatal (struct bfd_link_info *info,
   return fatal;
 }
 
-
-
+#define RELOCATE_CALC_PC32_HI20(relocation, pc) 	\
+  ({							\
+    bfd_vma lo = (relocation) & ((bfd_vma)0xfff);	\
+    pc = pc & (~(bfd_vma)0xfff);			\
+    if (lo > 0x7ff)					\
+      {							\
+	relocation += 0x1000;				\
+      } 						\
+    relocation &= ~(bfd_vma)0xfff;			\
+    relocation -= pc;					\
+  })
+
+#define RELOCATE_CALC_PC64_HI32(relocation, pc)  	\
+  ({							\
+    bfd_vma lo = (relocation) & ((bfd_vma)0xfff);	\
+    if (lo > 0x7ff)					\
+      { 						\
+	relocation -= 0x100000000;      		\
+      }  						\
+    relocation -= (pc & ~(bfd_vma)0xffffffff);  	\
+  })
 
 static int
 loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
@@ -1983,8 +2005,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
       bool is_ie, is_undefweak, unresolved_reloc, defined_local;
       bool resolved_local, resolved_dynly, resolved_to_const;
       char tls_type;
-      bfd_vma relocation;
-      bfd_vma off, ie_off;
+      bfd_vma relocation, off, ie_off;
       int i, j;
 
       howto = loongarch_elf_rtype_to_howto (input_bfd, r_type);
@@ -2018,9 +2039,12 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	  resolved_local = true;
 	  resolved_dynly = false;
 	  resolved_to_const = false;
+
+	  /* Calc in funtion elf_link_input_bfd,
+	   * if #define elf_backend_rela_normal to 1.  */
 	  if (bfd_link_relocatable (info)
 	      && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-	    rel->r_addend += sec->output_offset;
+	    continue;
 	}
       else
 	{
@@ -2092,7 +2116,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	  resolved_to_const = true;
 	}
 
-      /* The ifunc without reference does not generate plt.  */
+      /* The ifunc reference generate plt.  */
       if (h && h->type == STT_GNU_IFUNC && h->plt.offset != MINUS_ONE)
 	{
 	  defined_local = true;
@@ -2150,20 +2174,25 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 				     + h->root.u.def.section->output_section->vma
 				     + h->root.u.def.section->output_offset);
 
-		  /* Dynamic relocations are stored in
-		     1. .rela.ifunc section in PIC object.
-		     2. .rela.got section in dynamic executable.
-		     3. .rela.iplt section in static executable.  */
-		  if (bfd_link_pic (info))
-		    sreloc = htab->elf.irelifunc;
-		  else if (htab->elf.splt != NULL)
-		    sreloc = htab->elf.srelgot;
+		  if (htab->elf.splt != NULL)
+		    sreloc = htab->elf.srelplt;
 		  else
 		    sreloc = htab->elf.irelplt;
 		}
 	      else if (resolved_dynly)
 		{
-		  outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
+		  if (h->dynindx == -1)
+		    {
+		      if (h->root.type == bfd_link_hash_undefined)
+			(*info->callbacks->undefined_symbol)
+			  (info, name, input_bfd, input_section,
+			   rel->r_offset, true);
+
+		      outrel.r_info = ELFNN_R_INFO (0, r_type);
+		    }
+		  else
+		    outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
+
 		  outrel.r_addend = rel->r_addend;
 		}
 	      else
@@ -2172,7 +2201,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		  outrel.r_addend = relocation + rel->r_addend;
 		}
 
-	      if (unresolved_reloc)
+	      /* No alloc space of func allocate_dynrelocs.  */
+	      if (unresolved_reloc
+		  && !(h && (h->is_weakalias || !h->dyn_relocs)))
 		loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
 	    }
 
@@ -2341,12 +2372,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	case R_LARCH_SOP_PUSH_PLT_PCREL:
 	  unresolved_reloc = false;
 
-	  if (resolved_to_const)
-	    {
-	      relocation += rel->r_addend;
-	      break;
-	    }
-	  else if (is_undefweak)
+	  if (is_undefweak)
 	    {
 	      i = 0, j = 0;
 	      relocation = 0;
@@ -2427,7 +2453,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
 	  if (h != NULL)
 	    {
-	      off = h->got.offset;
+	      off = h->got.offset & (~1);
 
 	      if (off == MINUS_ONE
 		  && h->type != STT_GNU_IFUNC)
@@ -2455,79 +2481,76 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		  if (htab->elf.splt != NULL)
 		    {
 		      /* Section .plt header is 2 times of plt entry.  */
-		      off = sec_addr(htab->elf.sgotplt) + off
-			- sec_addr(htab->elf.sgot);
+		      off = sec_addr (htab->elf.sgotplt) + off
+			- sec_addr (htab->elf.sgot);
 		    }
 		  else
 		    {
 		      /* Section iplt not has plt header.  */
-		      off = sec_addr(htab->elf.igotplt) + off
-			- sec_addr(htab->elf.sgot);
+		      off = sec_addr (htab->elf.igotplt) + off
+			- sec_addr (htab->elf.sgot);
 		    }
 		}
 
-	      if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn, is_pic, h)
-		  || (is_pic && SYMBOL_REFERENCES_LOCAL (info, h)))
+	      if ((h->got.offset & 1) == 0)
 		{
-		  /* This is actually a static link, or it is a
-		     -Bsymbolic link and the symbol is defined
-		     locally, or the symbol was forced to be local
-		     because of a version file.  We must initialize
-		     this entry in the global offset table.  Since the
-		     offset must always be a multiple of the word size,
-		     we use the least significant bit to record whether
-		     we have initialized it already.
-
-		     When doing a dynamic link, we create a .rela.got
-		     relocation entry to initialize the value.  This
-		     is done in the finish_dynamic_symbol routine.  */
-
-		  if (resolved_dynly)
+		  if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
+							bfd_link_pic (info), h)
+		      && ((bfd_link_pic (info)
+			   && SYMBOL_REFERENCES_LOCAL (info, h))))
 		    {
-		      fatal = (loongarch_reloc_is_fatal
-			       (info, input_bfd, input_section, rel, howto,
-				bfd_reloc_dangerous, is_undefweak, name,
-				"Internal: here shouldn't dynamic."));
-		    }
+		      /* This is actually a static link, or it is a
+			 -Bsymbolic link and the symbol is defined
+			 locally, or the symbol was forced to be local
+			 because of a version file.  We must initialize
+			 this entry in the global offset table.  Since the
+			 offset must always be a multiple of the word size,
+			 we use the least significant bit to record whether
+			 we have initialized it already.
+
+			 When doing a dynamic link, we create a rela.got
+			 relocation entry to initialize the value.  This
+			 is done in the finish_dynamic_symbol routine.  */
+
+		      if (resolved_dynly)
+			{
+			  fatal = (loongarch_reloc_is_fatal
+				   (info, input_bfd, input_section, rel, howto,
+				    bfd_reloc_dangerous, is_undefweak, name,
+				    "Internal: here shouldn't dynamic."));
+			}
 
-		  if (!(defined_local || resolved_to_const))
-		    {
-		      fatal = (loongarch_reloc_is_fatal
-			       (info, input_bfd, input_section, rel, howto,
-				bfd_reloc_undefined, is_undefweak, name,
-				"Internal: "));
-		      break;
-		    }
+		      if (!(defined_local || resolved_to_const))
+			{
+			  fatal = (loongarch_reloc_is_fatal
+				   (info, input_bfd, input_section, rel, howto,
+				    bfd_reloc_undefined, is_undefweak, name,
+				    "Internal: "));
+			  break;
+			}
 
-		  if ((off & 1) != 0)
-		    off &= ~1;
-		  else
-		    {
-		      /* The pr21964-4. Create relocate entry.  */
-		      if (is_pic && h->start_stop)
+		      asection *s;
+		      Elf_Internal_Rela outrel;
+		      /* We need to generate a R_LARCH_RELATIVE reloc
+			 for the dynamic linker.  */
+		      s = htab->elf.srelgot;
+		      if (!s)
 			{
-			  asection *s;
-			  Elf_Internal_Rela outrel;
-			  /* We need to generate a R_LARCH_RELATIVE reloc
-			     for the dynamic linker.  */
-			  s = htab->elf.srelgot;
-			  if (!s)
-			    {
-			      fatal = loongarch_reloc_is_fatal (info, input_bfd,
-				    input_section, rel, howto,
-				    bfd_reloc_notsupported, is_undefweak, name,
-				    "Internal: '.rel.got' not represent");
-			      break;
-			    }
-
-			  outrel.r_offset = sec_addr (got) + off;
-			  outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
-			  outrel.r_addend = relocation; /* Link-time addr.  */
-			  loongarch_elf_append_rela (output_bfd, s, &outrel);
+			  fatal = loongarch_reloc_is_fatal
+			    (info, input_bfd,
+			     input_section, rel, howto,
+			     bfd_reloc_notsupported, is_undefweak, name,
+			     "Internal: '.rel.got' not represent");
+			  break;
 			}
-		      bfd_put_NN (output_bfd, relocation, got->contents + off);
-		      h->got.offset |= 1;
+
+		      outrel.r_offset = sec_addr (got) + off;
+		      outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
+		      outrel.r_addend = relocation; /* Link-time addr.  */
+		      loongarch_elf_append_rela (output_bfd, s, &outrel);
 		    }
+		  bfd_put_NN (output_bfd, relocation, got->contents + off);
+		  h->got.offset |= 1;
 		}
 	    }
 	  else
@@ -2541,7 +2564,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		  break;
 		}
 
-	      off = local_got_offsets[r_symndx];
+	      off = local_got_offsets[r_symndx] & (~1);
 
 	      if (off == MINUS_ONE)
 		{
@@ -2555,9 +2578,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	      /* The offset must always be a multiple of the word size.
 		 So, we can use the least significant bit to record
 		 whether we have already processed this entry.  */
-	      if ((off & 1) != 0)
-		off &= ~1;
-	      else
+	      if (local_got_offsets[r_symndx] == 0)
 		{
 		  if (is_pic)
 		    {
@@ -2586,160 +2607,519 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		}
 	    }
 	  relocation = off;
+
 	  break;
 
 	case R_LARCH_SOP_PUSH_TLS_GOT:
 	case R_LARCH_SOP_PUSH_TLS_GD:
-	  if (r_type == R_LARCH_SOP_PUSH_TLS_GOT)
-	    is_ie = true;
+	  {
+	    unresolved_reloc = false;
+	    if (r_type == R_LARCH_SOP_PUSH_TLS_GOT)
+	      is_ie = true;
+
+	    bfd_vma got_off = 0;
+	    if (h != NULL)
+	      {
+		got_off = h->got.offset;
+		h->got.offset |= 1;
+	      }
+	    else
+	      {
+		got_off = local_got_offsets[r_symndx];
+		local_got_offsets[r_symndx] |= 1;
+	      }
+
+	    BFD_ASSERT (got_off != MINUS_ONE);
+
+	    ie_off = 0;
+	    tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
+	    if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
+	      ie_off = 2 * GOT_ENTRY_SIZE;
+
+	    if ((got_off & 1) == 0)
+	      {
+		Elf_Internal_Rela rela;
+		asection *srel = htab->elf.srelgot;
+		bfd_vma tls_block_off = 0;
+
+		if (SYMBOL_REFERENCES_LOCAL (info, h))
+		  {
+		    BFD_ASSERT (elf_hash_table (info)->tls_sec);
+		    tls_block_off = relocation
+			- elf_hash_table (info)->tls_sec->vma;
+		  }
+
+		if (tls_type & GOT_TLS_GD)
+		  {
+		    rela.r_offset = sec_addr (got) + got_off;
+		    rela.r_addend = 0;
+		    if (SYMBOL_REFERENCES_LOCAL (info, h))
+		      {
+			/* Local sym, used in exec, set module id 1.  */
+			if (bfd_link_executable (info))
+			  bfd_put_NN (output_bfd, 1, got->contents + got_off);
+			else
+			  {
+			    rela.r_info = ELFNN_R_INFO (0,
+							R_LARCH_TLS_DTPMODNN);
+			    loongarch_elf_append_rela (output_bfd, srel, &rela);
+			  }
+
+			bfd_put_NN (output_bfd, tls_block_off,
+				    got->contents + got_off + GOT_ENTRY_SIZE);
+		      }
+		    /* Dynamic resolved.  */
+		    else
+		      {
+			/* Dynamic relocate module id.  */
+			rela.r_info = ELFNN_R_INFO (h->dynindx,
+						    R_LARCH_TLS_DTPMODNN);
+			loongarch_elf_append_rela (output_bfd, srel, &rela);
+
+			/* Dynamic relocate offset of block.  */
+			rela.r_offset += GOT_ENTRY_SIZE;
+			rela.r_info = ELFNN_R_INFO (h->dynindx,
+						    R_LARCH_TLS_DTPRELNN);
+			loongarch_elf_append_rela (output_bfd, srel, &rela);
+		      }
+		  }
+		if (tls_type & GOT_TLS_IE)
+		  {
+		    rela.r_offset = sec_addr (got) + got_off + ie_off;
+		    if (SYMBOL_REFERENCES_LOCAL (info, h))
+		      {
+			/* Local sym, used in exec, set module id 1.  */
+			if (!bfd_link_executable (info))
+			  {
+			    rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
+			    rela.r_addend = tls_block_off;
+			    loongarch_elf_append_rela (output_bfd, srel, &rela);
+			  }
+
+			bfd_put_NN (output_bfd, tls_block_off,
+				    got->contents + got_off + ie_off);
+		      }
+		    /* Dynamic resolved.  */
+		    else
+		      {
+			/* Dynamic relocate offset of block.  */
+			rela.r_info = ELFNN_R_INFO (h->dynindx,
+						    R_LARCH_TLS_TPRELNN);
+			rela.r_addend = 0;
+			loongarch_elf_append_rela (output_bfd, srel, &rela);
+		      }
+		  }
+	      }
+
+	    relocation = (got_off & (~(bfd_vma)1)) + (is_ie ? ie_off : 0);
+	  }
+	  break;
+
+	/* New reloc types.  */
+	case R_LARCH_B21:
+	case R_LARCH_B26:
+	case R_LARCH_B16:
 	  unresolved_reloc = false;
+	  if (is_undefweak)
+	    {
+	      relocation = 0;
+	    }
 
-	  if (rel->r_addend != 0)
+	  if (resolved_local)
 	    {
-	      fatal = (loongarch_reloc_is_fatal
-		       (info, input_bfd, input_section, rel, howto,
-			bfd_reloc_notsupported, is_undefweak, name,
-			"Shouldn't be with r_addend."));
+	      relocation -= pc;
+	      relocation += rel->r_addend;
+	    }
+	  else if (resolved_dynly)
+	    {
+	      BFD_ASSERT (h
+			  && (h->plt.offset != MINUS_ONE
+			      || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+			  && rel->r_addend == 0);
+	      if (h && h->plt.offset == MINUS_ONE
+		  && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+		{
+		  relocation -= pc;
+		  relocation += rel->r_addend;
+		}
+	      else
+		relocation = sec_addr (plt) + h->plt.offset - pc;
+	    }
+
+	  break;
+
+	case R_LARCH_ABS_HI20:
+	case R_LARCH_ABS_LO12:
+	case R_LARCH_ABS64_LO20:
+	case R_LARCH_ABS64_HI12:
+	  BFD_ASSERT (!is_pic);
+
+	  if (is_undefweak)
+	    {
+	      BFD_ASSERT (resolved_dynly);
+	      relocation = 0;
 	      break;
 	    }
+	  else if (resolved_to_const || resolved_local)
+	    {
+	      relocation += rel->r_addend;
+	    }
+	  else if (resolved_dynly)
+	    {
+	      unresolved_reloc = false;
+	      BFD_ASSERT ((plt && h && h->plt.offset != MINUS_ONE)
+			  && rel->r_addend == 0);
+	      relocation = sec_addr (plt) + h->plt.offset;
+	    }
 
+	  break;
+
+	case R_LARCH_PCALA_HI20:
+	  unresolved_reloc = false;
+	  if (h && h->plt.offset != MINUS_ONE)
+	    relocation = sec_addr (plt) + h->plt.offset;
+	  else
+	    relocation += rel->r_addend;
+
+	  RELOCATE_CALC_PC32_HI20 (relocation, pc);
+
+	  break;
+
+	case R_LARCH_PCALA_LO12:
+	  /* Not support if sym_addr in 2k page edge.
+	     pcalau12i pc_hi20 (sym_addr)
+	     ld.w/d pc_lo12 (sym_addr)
+	     ld.w/d pc_lo12 (sym_addr + x)
+	     ...
+	     can not calc correct address
+	     if sym_addr < 0x800 && sym_addr + x >= 0x800.  */
+
+	  if (h && h->plt.offset != MINUS_ONE)
+	    relocation = sec_addr (plt) + h->plt.offset;
+	  else
+	    relocation += rel->r_addend;
 
-	  if (resolved_to_const && is_undefweak && h->dynindx != -1)
 	    {
-	      /* What if undefweak? Let rtld make a decision.  */
-	      resolved_to_const = resolved_local = false;
-	      resolved_dynly = true;
+	      relocation &= 0xfff;
+	      /* Signed extend.  */
+	      relocation = (relocation ^ 0x800) - 0x800;
+
+	      /* For 2G jump, generate pcalau12i, jirl.  */
+	      /* If use jirl, turns to R_LARCH_B16.  */
+	      uint32_t insn = bfd_get (32, input_bfd, contents + rel->r_offset);
+	      if ((insn & 0x4c000000) == 0x4c000000)
+		{
+		  rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_B16);
+		  howto = loongarch_elf_rtype_to_howto (input_bfd, R_LARCH_B16);
+		}
 	    }
+	  break;
 
-	  if (resolved_to_const)
+	case R_LARCH_PCALA64_LO20:
+	case R_LARCH_PCALA64_HI12:
+	  if (h && h->plt.offset != MINUS_ONE)
 	    {
-	      fatal = (loongarch_reloc_is_fatal
-		       (info, input_bfd, input_section, rel, howto,
-			bfd_reloc_notsupported, is_undefweak, name,
-			"Internal: Shouldn't be resolved to const."));
-	      break;
+	      BFD_ASSERT (rel->r_addend == 0);
+	      relocation = sec_addr (plt) + h->plt.offset;
+	    }
+	  else
+	    relocation += rel->r_addend;
+
+	  RELOCATE_CALC_PC64_HI32 (relocation, pc);
+
+	  break;
+
+	case R_LARCH_GOT_PC_HI20:
+	case R_LARCH_GOT64_HI20:
+	  /* Calc got offset.  */
+	    {
+	      unresolved_reloc = false;
+	      BFD_ASSERT (rel->r_addend == 0);
+
+	      bfd_vma got_off = 0;
+	      if (h != NULL)
+		{
+		  /* GOT ref or ifunc.  */
+		  BFD_ASSERT (h->got.offset != MINUS_ONE
+			      || h->type == STT_GNU_IFUNC);
+
+		  got_off = h->got.offset  & (~(bfd_vma)1);
+		  /* Hidden symbol not has got entry,
+		   * only got.plt entry so it is (plt - got).  */
+		  if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
+		    {
+		      bfd_vma idx;
+		      if (htab->elf.splt != NULL)
+			{
+			  idx = (h->plt.offset - PLT_HEADER_SIZE)
+			    / PLT_ENTRY_SIZE;
+			  got_off = sec_addr (htab->elf.sgotplt)
+			    + GOTPLT_HEADER_SIZE
+			    + (idx * GOT_ENTRY_SIZE)
+			    - sec_addr (htab->elf.sgot);
+			}
+		      else
+			{
+			  idx = h->plt.offset / PLT_ENTRY_SIZE;
+			  got_off = sec_addr (htab->elf.sgotplt)
+			    + (idx * GOT_ENTRY_SIZE)
+			    - sec_addr (htab->elf.sgot);
+			}
+		    }
+
+		  if ((h->got.offset & 1) == 0)
+		    {
+		      /* We need to generate a R_LARCH_RELATIVE reloc once
+		       * in loongarch_elf_finish_dynamic_symbol or now,
+		       * call finish_dyn && nopic
+		       * or !call finish_dyn && pic.  */
+		      if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
+							    bfd_link_pic (info),
+							    h)
+			  && bfd_link_pic (info)
+			  && SYMBOL_REFERENCES_LOCAL (info, h))
+			{
+			  Elf_Internal_Rela rela;
+			  rela.r_offset = sec_addr (got) + got_off;
+			  rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
+			  rela.r_addend = relocation;
+			  loongarch_elf_append_rela (output_bfd,
+						     htab->elf.srelgot, &rela);
+			}
+		      h->got.offset |= 1;
+		    }
+		}
+	      else
+		{
+		  BFD_ASSERT (local_got_offsets
+			      && local_got_offsets[r_symndx] != MINUS_ONE);
+
+		  got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
+		  if ((local_got_offsets[r_symndx] & 1) == 0)
+		    {
+		      if (bfd_link_pic (info))
+			{
+			  Elf_Internal_Rela rela;
+			  rela.r_offset = sec_addr (got) + got_off;
+			  rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
+			  rela.r_addend = relocation;
+			  loongarch_elf_append_rela (output_bfd,
+						     htab->elf.srelgot, &rela);
+			}
+		      local_got_offsets[r_symndx] |= 1;
+		    }
+		}
+
+	      bfd_put_NN (output_bfd, relocation, got->contents + got_off);
+
+	      relocation = got_off + sec_addr (got);
 	    }
 
+	  if (r_type == R_LARCH_GOT_PC_HI20)
+	    RELOCATE_CALC_PC32_HI20 (relocation, pc);
+
+	  break;
+
+	case R_LARCH_GOT_PC_LO12:
+	case R_LARCH_GOT64_PC_LO20:
+	case R_LARCH_GOT64_PC_HI12:
+	case R_LARCH_GOT64_LO12:
+	case R_LARCH_GOT64_LO20:
+	case R_LARCH_GOT64_HI12:
+	    {
+	      unresolved_reloc = false;
+	      bfd_vma got_off;
+	      if (h)
+		got_off = h->got.offset & (~(bfd_vma)1);
+	      else
+		got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
+
+	      if (h && h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
+		{
+		  bfd_vma idx;
+		  if (htab->elf.splt != NULL)
+		    idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
+		  else
+		    idx = h->plt.offset / PLT_ENTRY_SIZE;
+
+		  got_off = sec_addr (htab->elf.sgotplt)
+		    + GOTPLT_HEADER_SIZE
+		    + (idx * GOT_ENTRY_SIZE)
+		    - sec_addr (htab->elf.sgot);
+		}
+	      relocation = got_off + sec_addr (got);
+	    }
+
+	  if (r_type == R_LARCH_GOT_PC_LO12)
+	    relocation &= (bfd_vma)0xfff;
+	  else if (r_type == R_LARCH_GOT64_PC_LO20
+		   || r_type == R_LARCH_GOT64_PC_HI12)
+	    RELOCATE_CALC_PC64_HI32 (relocation, pc);
+
+	  break;
+
+	case R_LARCH_TLS_LE_HI20:
+	case R_LARCH_TLS_LE_LO12:
+	case R_LARCH_TLS_LE64_LO20:
+	case R_LARCH_TLS_LE64_HI12:
+	  BFD_ASSERT (resolved_local && elf_hash_table (info)->tls_sec);
+
+	  relocation -= elf_hash_table (info)->tls_sec->vma;
+	  break;
+
+	/* TLS IE LD/GD process separately is troublesome.
+	   When a symbol is both ie and LD/GD, h->got.off |= 1
+	   make only one type be relocated.  We must use
+	   h->got.offset |= 1 and h->got.offset |= 2
+	   diff IE and LD/GD.  And all (got_off & (~(bfd_vma)1))
+	   (IE LD/GD and reusable GOT reloc) must change to
+	   (got_off & (~(bfd_vma)3)), beause we use lowest 2 bits
+	   as a tag.
+	   Now, LD and GD is both GOT_TLS_GD type, LD seems to
+	   can be omitted.  */
+	case R_LARCH_TLS_IE_PC_HI20:
+	case R_LARCH_TLS_IE64_HI20:
+	case R_LARCH_TLS_LD_PC_HI20:
+	case R_LARCH_TLS_LD64_HI20:
+	case R_LARCH_TLS_GD_PC_HI20:
+	case R_LARCH_TLS_GD64_HI20:
+	  BFD_ASSERT (rel->r_addend == 0);
+	  unresolved_reloc = false;
+
+	  if (r_type == R_LARCH_TLS_IE_PC_HI20
+	      || r_type == R_LARCH_TLS_IE64_HI20)
+	    is_ie = true;
+
+	  bfd_vma got_off = 0;
 	  if (h != NULL)
 	    {
-	      off = h->got.offset;
+	      got_off = h->got.offset;
 	      h->got.offset |= 1;
 	    }
 	  else
 	    {
-	      off = local_got_offsets[r_symndx];
+	      got_off = local_got_offsets[r_symndx];
 	      local_got_offsets[r_symndx] |= 1;
 	    }
 
-	  if (off == MINUS_ONE)
-	    {
-	      fatal = (loongarch_reloc_is_fatal
-		       (info, input_bfd, input_section, rel, howto,
-			bfd_reloc_notsupported, is_undefweak, name,
-			"Internal: TLS GOT entry doesn't represent."));
-	      break;
-	    }
-
-	  tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
+	  BFD_ASSERT (got_off != MINUS_ONE);
 
-	  /* If this symbol is referenced by both GD and IE TLS, the IE
-	     reference's GOT slot follows the GD reference's slots.  */
 	  ie_off = 0;
+	  tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
 	  if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
 	    ie_off = 2 * GOT_ENTRY_SIZE;
 
-	  if ((off & 1) != 0)
-	    off &= ~1;
-	  else
+	  if ((got_off & 1) == 0)
 	    {
+	      Elf_Internal_Rela rela;
+	      asection *relgot = htab->elf.srelgot;
 	      bfd_vma tls_block_off = 0;
-	      Elf_Internal_Rela outrel;
 
-	      if (resolved_local)
+	      if (SYMBOL_REFERENCES_LOCAL (info, h))
 		{
-		  if (!elf_hash_table (info)->tls_sec)
-		    {
-		      fatal = (loongarch_reloc_is_fatal
-			       (info, input_bfd, input_section, rel, howto,
-				bfd_reloc_notsupported, is_undefweak, name,
-				"Internal: TLS sec not represent."));
-		      break;
-		    }
-		  tls_block_off =
-		    relocation - elf_hash_table (info)->tls_sec->vma;
+		  BFD_ASSERT (elf_hash_table (info)->tls_sec);
+		  tls_block_off = relocation
+		      - elf_hash_table (info)->tls_sec->vma;
 		}
 
 	      if (tls_type & GOT_TLS_GD)
 		{
-		  outrel.r_offset = sec_addr (got) + off;
-		  outrel.r_addend = 0;
-		  bfd_put_NN (output_bfd, 0, got->contents + off);
-		  if (resolved_local && bfd_link_executable (info))
-		    bfd_put_NN (output_bfd, 1, got->contents + off);
-		  else if (resolved_local /* && !bfd_link_executable (info) */)
-		    {
-		      outrel.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN);
-		      loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
-						 &outrel);
-		    }
-		  else /* if (resolved_dynly) */
+		  rela.r_offset = sec_addr (got) + got_off;
+		  rela.r_addend = 0;
+		  if (SYMBOL_REFERENCES_LOCAL (info, h))
 		    {
-		      outrel.r_info =
-			ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_DTPMODNN);
-		      loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
-						 &outrel);
-		    }
+		      /* Local sym, used in exec, set module id 1.  */
+		      if (bfd_link_executable (info))
+			bfd_put_NN (output_bfd, 1, got->contents + got_off);
+		      else
+			{
+			  rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN);
+			  loongarch_elf_append_rela (output_bfd, relgot, &rela);
+			}
 
-		  outrel.r_offset += GOT_ENTRY_SIZE;
-		  bfd_put_NN (output_bfd, tls_block_off,
-			      got->contents + off + GOT_ENTRY_SIZE);
-		  if (resolved_local)
-		    /* DTPREL known.  */;
-		  else /* if (resolved_dynly) */
+		      bfd_put_NN (output_bfd, tls_block_off,
+				  got->contents + got_off + GOT_ENTRY_SIZE);
+		    }
+		  /* Dynamic resolved.  */
+		  else
 		    {
-		      outrel.r_info =
-			ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_DTPRELNN);
-		      loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
-						 &outrel);
+		      /* Dynamic relocate module id.  */
+		      rela.r_info = ELFNN_R_INFO (h->dynindx,
+						  R_LARCH_TLS_DTPMODNN);
+		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
+
+		      /* Dynamic relocate offset of block.  */
+		      rela.r_offset += GOT_ENTRY_SIZE;
+		      rela.r_info = ELFNN_R_INFO (h->dynindx,
+						  R_LARCH_TLS_DTPRELNN);
+		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
 		    }
 		}
-
 	      if (tls_type & GOT_TLS_IE)
 		{
-		  outrel.r_offset = sec_addr (got) + off + ie_off;
-		  bfd_put_NN (output_bfd, tls_block_off,
-			      got->contents + off + ie_off);
-		  if (resolved_local && bfd_link_executable (info))
-		    /* TPREL known.  */;
-		  else if (resolved_local /* && !bfd_link_executable (info) */)
+		  rela.r_offset = sec_addr (got) + got_off + ie_off;
+		  if (SYMBOL_REFERENCES_LOCAL (info, h))
 		    {
-		      outrel.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
-		      outrel.r_addend = tls_block_off;
-		      loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
-						 &outrel);
-		    }
-		  else /* if (resolved_dynly) */
-		    {
-		      /* Static linking has no .dynsym table.  */
-		      if (!htab->elf.dynamic_sections_created)
-			{
-			  outrel.r_info =
-			    ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
-			  outrel.r_addend = 0;
-			}
-		      else
+		      /* Local sym, used in exec, set module id 1.  */
+		      if (!bfd_link_executable (info))
 			{
-			  outrel.r_info =
-			    ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_TPRELNN);
-			  outrel.r_addend = 0;
+			  rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
+			  rela.r_addend = tls_block_off;
+			  loongarch_elf_append_rela (output_bfd, relgot, &rela);
 			}
-		      loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
-						 &outrel);
+
+		      bfd_put_NN (output_bfd, tls_block_off,
+				  got->contents + got_off + ie_off);
+		    }
+		  /* Dynamic resolved.  */
+		  else
+		    {
+		      /* Dynamic relocate offset of block.  */
+		      rela.r_info = ELFNN_R_INFO (h->dynindx,
+						  R_LARCH_TLS_TPRELNN);
+		      rela.r_addend = 0;
+		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
 		    }
 		}
 	    }
+	  relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got)
+			+ (is_ie ? ie_off : 0);
+
+	  if (r_type == R_LARCH_TLS_LD_PC_HI20
+	      || r_type == R_LARCH_TLS_GD_PC_HI20
+	      || r_type == R_LARCH_TLS_IE_PC_HI20)
+	    RELOCATE_CALC_PC32_HI20 (relocation, pc);
 
-	  relocation = off + (is_ie ? ie_off : 0);
+	  break;
+
+	case R_LARCH_TLS_IE_PC_LO12:
+	case R_LARCH_TLS_IE64_PC_LO20:
+	case R_LARCH_TLS_IE64_PC_HI12:
+	case R_LARCH_TLS_IE64_LO12:
+	case R_LARCH_TLS_IE64_LO20:
+	case R_LARCH_TLS_IE64_HI12:
+	  unresolved_reloc = false;
+
+	  if (h)
+	    relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)3));
+	  else
+	    relocation = sec_addr (got)
+	      + (local_got_offsets[r_symndx] & (~(bfd_vma)3));
+
+	  tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
+	  /* Use both TLS_GD and TLS_IE.  */
+	  if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
+	    relocation += 2 * GOT_ENTRY_SIZE;
+
+	  if (r_type == R_LARCH_TLS_IE_PC_LO12)
+	    relocation &= (bfd_vma)0xfff;
+	  else if (r_type == R_LARCH_TLS_IE64_PC_LO20
+		   || r_type == R_LARCH_TLS_IE64_PC_HI12)
+	    RELOCATE_CALC_PC64_HI32 (relocation, pc);
+
+	  break;
+
+	case R_LARCH_RELAX:
 	  break;
 
 	default:
@@ -2759,7 +3139,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	  if (_bfd_elf_section_offset (output_bfd, info, input_section,
 				       rel->r_offset) == MINUS_ONE)
 	    /* WHY? May because it's invalid so skip checking.
-	       But why dynamic reloc a invalid section? */
+	       But why dynamic reloc a invalid section?  */
 	    break;
 
 	  if (input_section->output_section->flags & SEC_DEBUGGING)
@@ -2825,7 +3205,6 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	}
 
       fatal = true;
-      break;
     }
 
   return !fatal;
@@ -2889,27 +3268,15 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
       for (i = 0; i < PLT_ENTRY_INSNS; i++)
 	bfd_put_32 (output_bfd, plt_entry[i], loc + 4 * i);
 
-      /* Fill in the initial value of the .got.plt entry.  */
+      /* Fill in the initial value of the got.plt entry.  */
       loc = gotplt->contents + (got_address - sec_addr (gotplt));
       bfd_put_NN (output_bfd, sec_addr (plt), loc);
 
       rela.r_offset = got_address;
 
-      /* TRUE if this is a PLT reference to a local IFUNC.  */
-      if (PLT_LOCAL_IFUNC_P(info, h))
-	{
-	  rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
-	  rela.r_addend = (h->root.u.def.value
-			   + h->root.u.def.section->output_section->vma
-			   + h->root.u.def.section->output_offset);
-	}
-      else
-	{
-	  /* Fill in the entry in the .rela.plt section.  */
-	  rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT);
-	  rela.r_addend = 0;
-	}
-
+      /* Fill in the entry in the rela.plt section.  */
+      rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT);
+      rela.r_addend = 0;
       loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela);
       bed->s->swap_reloca_out (output_bfd, &rela, loc);
 
@@ -2930,15 +3297,14 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
   if (h->got.offset != MINUS_ONE
       /* TLS got entry have been handled in elf_relocate_section.  */
       && !(loongarch_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE))
-      /* have allocated got entry but not allocated rela before.  */
+      /* Have allocated got entry but not allocated rela before.  */
       && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
     {
       asection *sgot, *srela;
       Elf_Internal_Rela rela;
-      bfd_vma off = h->got.offset & ~(bfd_vma) 1;
+      bfd_vma off = h->got.offset & ~(bfd_vma)1;
 
       /* This symbol has an entry in the GOT.  Set it up.  */
-
       sgot = htab->elf.sgot;
       srela = htab->elf.srelgot;
       BFD_ASSERT (sgot && srela);
@@ -2963,7 +3329,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
 		}
 	      else
 		{
-		  BFD_ASSERT ((h->got.offset & 1) == 0);
 		  BFD_ASSERT (h->dynindx != -1);
 		  rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
 		  rela.r_addend = 0;
@@ -2993,7 +3358,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
 	}
       else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))
 	{
-	  BFD_ASSERT (h->got.offset & 1 /* Has been filled in addr.  */);
 	  asection *sec = h->root.u.def.section;
 	  rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
 	  rela.r_addend = (h->root.u.def.value + sec->output_section->vma
@@ -3001,7 +3365,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
 	}
       else
 	{
-	  BFD_ASSERT ((h->got.offset & 1) == 0);
 	  BFD_ASSERT (h->dynindx != -1);
 	  rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
 	  rela.r_addend = 0;
@@ -3010,24 +3373,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
       loongarch_elf_append_rela (output_bfd, srela, &rela);
     }
 
-  if (h->needs_copy)
-    {
-      Elf_Internal_Rela rela;
-      asection *s;
-
-      /* This symbols needs a copy reloc.  Set it up.  */
-      BFD_ASSERT (h->dynindx != -1);
-
-      rela.r_offset = sec_addr (h->root.u.def.section) + h->root.u.def.value;
-      rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_COPY);
-      rela.r_addend = 0;
-      if (h->root.u.def.section == htab->elf.sdynrelro)
-	s = htab->elf.sreldynrelro;
-      else
-	s = htab->elf.srelbss;
-      loongarch_elf_append_rela (output_bfd, s, &rela);
-    }
-
   /* Mark some specially defined symbols as absolute.  */
   if (h == htab->elf.hdynamic || h == htab->elf.hgot || h == htab->elf.hplt)
     sym->st_shndx = SHN_ABS;
@@ -3337,7 +3682,6 @@ loongarch_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 #define PRPSINFO_OFFSET_PR_PS_ARGS  0x38
 #define PRPSINFO_SIZEOF_PR_PS_ARGS  0x50
 
-
 static bool
 loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 {
diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
index 4424969e579..1f6346ef5f3 100644
--- a/bfd/elfxx-loongarch.c
+++ b/bfd/elfxx-loongarch.c
@@ -35,27 +35,30 @@ typedef struct loongarch_reloc_howto_type_struct
   reloc_howto_type howto;
   bfd_reloc_code_real_type bfd_type;
   bool (*adjust_reloc_bits)(reloc_howto_type *, bfd_vma *);
-}loongarch_reloc_howto_type;
+  const char *larch_reloc_type_name;
+} loongarch_reloc_howto_type;
 
 #define LOONGARCH_DEFAULT_HOWTO(r_name)					    \
   { HOWTO (R_LARCH_##r_name, 0, 4, 32, false, 0, complain_overflow_signed,  \
 	bfd_elf_generic_reloc, "R_LARCH_" #r_name, false, 0, ALL_ONES,	    \
-	false), BFD_RELOC_LARCH_##r_name, NULL }
+	false), BFD_RELOC_LARCH_##r_name, NULL, NULL }
 
 #define LOONGARCH_HOWTO(type, right, size, bits, pcrel, left, ovf, func,  \
-	    name, inplace, src_mask, dst_mask, pcrel_off, btype, afunc)	  \
+	    name, inplace, src_mask, dst_mask, pcrel_off, btype, afunc,lname) \
   { HOWTO(type, right, size, bits, pcrel, left, ovf, func, name,	  \
-	  inplace, src_mask, dst_mask, pcrel_off), btype, afunc }
+	  inplace, src_mask, dst_mask, pcrel_off), btype, afunc, lname }
 
 #define LOONGARCH_EMPTY_HOWTO(C) \
-  { EMPTY_HOWTO(C), BFD_RELOC_NONE, NULL }
-
-bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *val);
-bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
-					     bfd_vma *fix_val);
-bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
-					  bfd_vma *val);
+  { EMPTY_HOWTO (C), BFD_RELOC_NONE, NULL, NULL }
 
+static bool
+reloc_bits (reloc_howto_type *howto, bfd_vma *val);
+static bool
+reloc_bits_b16 (reloc_howto_type *howto, bfd_vma *fix_val);
+static bool
+reloc_bits_b21 (reloc_howto_type *howto, bfd_vma *fix_val);
+static bool
+reloc_bits_b26 (reloc_howto_type *howto, bfd_vma *val);
 
 /* This does not include any relocation information, but should be
    good enough for GDB or objdump to read the file.  */
@@ -76,7 +79,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 0,				  /* dst_mask */
 	 false,				  /* pcrel_offset */
 	 BFD_RELOC_NONE,		  /* bfd_reloc_code_real_type */
-	 NULL),				  /* adjust_reloc_bits */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
   /* 32 bit relocation.  */
   LOONGARCH_HOWTO (R_LARCH_32,		  /* type (1).  */
@@ -93,7 +97,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 ALL_ONES,			  /* dst_mask */
 	 false,				  /* pcrel_offset */
 	 BFD_RELOC_32,			  /* bfd_reloc_code_real_type */
-	 NULL),				  /* adjust_reloc_bits */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
   /* 64 bit relocation.  */
   LOONGARCH_HOWTO (R_LARCH_64,		  /* type (2).  */
@@ -110,7 +115,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 ALL_ONES,			  /* dst_mask */
 	 false,				  /* pcrel_offset */
 	 BFD_RELOC_64,			  /* bfd_reloc_code_real_type */
-	 NULL),				  /* adjust_reloc_bits */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_RELATIVE,	  /* type (3).  */
 	 0,				  /* rightshift */
@@ -126,7 +132,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 ALL_ONES,			  /* dst_mask */
 	 false,				  /* pcrel_offset */
 	 BFD_RELOC_NONE,		  /* undefined?  */
-	 NULL),				  /* adjust_reloc_bits */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_COPY,	  /* type (4).  */
 	 0,				  /* rightshift */
@@ -141,8 +148,9 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 0,				  /* src_mask */
 	 0,				  /* dst_mask */
 	 false,				  /* pcrel_offset */
-	 BFD_RELOC_NONE,			  /* undefined?  */
-	 NULL),				  /* adjust_reloc_bits */
+	 BFD_RELOC_NONE,		  /* undefined?  */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_JUMP_SLOT,	  /* type (5).  */
 	 0,				  /* rightshift */
@@ -157,8 +165,9 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 0,				  /* src_mask */
 	 0,				  /* dst_mask */
 	 false,				  /* pcrel_offset */
-	 BFD_RELOC_NONE,			  /* undefined?  */
-	 NULL),				  /* adjust_reloc_bits */
+	 BFD_RELOC_NONE,		  /* undefined?  */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
   /* Dynamic TLS relocations.  */
   LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD32,  /* type (6).  */
@@ -175,7 +184,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 ALL_ONES,			  /* dst_mask */
 	 false,				  /* pcrel_offset */
 	 BFD_RELOC_LARCH_TLS_DTPMOD32,	  /* bfd_reloc_code_real_type */
-	 NULL),				  /* adjust_reloc_bits */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD64,  /* type (7).  */
 	 0,				  /* rightshift */
@@ -191,7 +201,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 ALL_ONES,			  /* dst_mask */
 	 false,				  /* pcrel_offset */
 	 BFD_RELOC_LARCH_TLS_DTPMOD64,	  /* bfd_reloc_code_real_type */
-	 NULL),				  /* adjust_reloc_bits */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL32,  /* type (8). */
 	 0,				  /* rightshift */
@@ -207,7 +218,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 ALL_ONES,			  /* dst_mask */
 	 false,				  /* pcrel_offset */
 	 BFD_RELOC_LARCH_TLS_DTPREL32,	  /* bfd_reloc_code_real_type */
-	 NULL),				  /* adjust_reloc_bits */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL64,  /* type (9).  */
 	 0,				  /* rightshift */
@@ -223,7 +235,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 ALL_ONES,			  /* dst_mask */
 	 false,				  /* pcrel_offset */
 	 BFD_RELOC_LARCH_TLS_DTPREL64,	  /* bfd_reloc_code_real_type */
-	 NULL),				  /* adjust_reloc_bits */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_TLS_TPREL32,	  /* type (10).  */
 	 0,				  /* rightshift */
@@ -239,7 +252,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 ALL_ONES,			  /* dst_mask */
 	 false,				  /* pcrel_offset */
 	 BFD_RELOC_LARCH_TLS_TPREL32,	  /* bfd_reloc_code_real_type */
-	 NULL),				  /* adjust_reloc_bits */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_TLS_TPREL64,	  /* type (11).  */
 	 0,				  /* rightshift */
@@ -255,7 +269,8 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 ALL_ONES,			  /* dst_mask */
 	 false,				  /* pcrel_offset */
 	 BFD_RELOC_LARCH_TLS_TPREL64,	  /* bfd_reloc_code_real_type */
-	 NULL),				  /* adjust_reloc_bits */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_IRELATIVE,	  /* type (12).  */
 	 0,				  /* rightshift */
@@ -271,63 +286,67 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 ALL_ONES,			  /* dst_mask */
 	 false,				  /* pcrel_offset */
 	 BFD_RELOC_NONE,		  /* undefined?  */
-	 NULL),				  /* adjust_reloc_bits */
+	 NULL,				  /* adjust_reloc_bits */
+	 NULL),				  /* larch_reloc_type_name */
 
-  LOONGARCH_EMPTY_HOWTO(13),
-  LOONGARCH_EMPTY_HOWTO(14),
-  LOONGARCH_EMPTY_HOWTO(15),
-  LOONGARCH_EMPTY_HOWTO(16),
-  LOONGARCH_EMPTY_HOWTO(17),
-  LOONGARCH_EMPTY_HOWTO(18),
-  LOONGARCH_EMPTY_HOWTO(19),
+  LOONGARCH_EMPTY_HOWTO (13),
+  LOONGARCH_EMPTY_HOWTO (14),
+  LOONGARCH_EMPTY_HOWTO (15),
+  LOONGARCH_EMPTY_HOWTO (16),
+  LOONGARCH_EMPTY_HOWTO (17),
+  LOONGARCH_EMPTY_HOWTO (18),
+  LOONGARCH_EMPTY_HOWTO (19),
 
   LOONGARCH_HOWTO (R_LARCH_MARK_LA,		/* type (20).  */
-	 0,				   	/* rightshift.  */
-	 0,				   	/* size.  */
-	 0,				  	/* bitsize.  */
+	 0,					/* rightshift.  */
+	 0,					/* size.  */
+	 0,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
 	 "R_LARCH_MARK_LA",			/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask.  */
 	 0,					/* dst_mask.  */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_MARK_LA,		/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_MARK_PCREL,		/* type (21).  */
-	 0,				   	/* rightshift.  */
-	 0,				   	/* size.  */
-	 0,				  	/* bitsize.  */
+	 0,					/* rightshift.  */
+	 0,					/* size.  */
+	 0,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
 	 "R_LARCH_MARK_PCREL",			/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask.  */
 	 0,					/* dst_mask.  */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_MARK_PCREL,		/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL,	/* type (22).  */
-	 2,				   	/* rightshift.  */
-	 4,				   	/* size.  */
-	 32,				  	/* bitsize.  */
+	 2,					/* rightshift.  */
+	 4,					/* size.  */
+	 32,					/* bitsize.  */
 	 true /* FIXME: somewhat use this.  */,	/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SOP_PUSH_PCREL",	    	/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_SOP_PUSH_PCREL",		/* name.  */
+	 false,					/* partial_inplace.  */
 	 0x03ffffff,				/* src_mask.  */
 	 0x03ffffff,				/* dst_mask.  */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_SOP_PUSH_PCREL,	/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
   /* type 23-37.  */
   LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_ABSOLUTE),
@@ -347,343 +366,984 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
   LOONGARCH_DEFAULT_HOWTO (SOP_IF_ELSE),
 
   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5,	  /* type (38).  */
-	 0,				   	  /* rightshift.  */
-	 4,				   	  /* size.  */
-	 5,				  	  /* bitsize.  */
+	 0,					  /* rightshift.  */
+	 4,					  /* size.  */
+	 5,					  /* bitsize.  */
 	 false,					  /* pc_relative.  */
-	 10,				   	  /* bitpos.  */
-	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		  /* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_10_5",	    	  /* name.  */
-	 false,			       		  /* partial_inplace.  */
+	 10,					  /* bitpos.  */
+	 complain_overflow_signed,		  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_10_5",		  /* name.  */
+	 false,					  /* partial_inplace.  */
 	 0,					  /* src_mask */
 	 0x7c00,				  /* dst_mask */
 	 false,					  /* pcrel_offset */
 	 BFD_RELOC_LARCH_SOP_POP_32_S_10_5,	  /* bfd_reloc_code_real_type */
-	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
+	 reloc_bits,				  /* adjust_reloc_bits */
+	 NULL),					  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12,	  /* type (39).  */
-	 0,				   	  /* rightshift.  */
-	 4,				   	  /* size.  */
-	 12,				  	  /* bitsize.  */
+	 0,					  /* rightshift.  */
+	 4,					  /* size.  */
+	 12,					  /* bitsize.  */
 	 false,					  /* pc_relative.  */
-	 10,				   	  /* bitpos.  */
-	 complain_overflow_unsigned,	    	  /* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		  /* special_function.  */
-	 "R_LARCH_SOP_POP_32_U_10_12",	    	  /* name.  */
-	 false,			       		  /* partial_inplace.  */
+	 10,					  /* bitpos.  */
+	 complain_overflow_unsigned,		  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_U_10_12",		  /* name.  */
+	 false,					  /* partial_inplace.  */
 	 0,					  /* src_mask */
 	 0x3ffc00,				  /* dst_mask */
 	 false,					  /* pcrel_offset */
 	 BFD_RELOC_LARCH_SOP_POP_32_U_10_12,	  /* bfd_reloc_code_real_type */
-	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
+	 reloc_bits,				  /* adjust_reloc_bits */
+	 NULL),					  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12,	  /* type (40).  */
-	 0,				   	  /* rightshift.  */
-	 4,				   	  /* size.  */
-	 12,				  	  /* bitsize.  */
+	 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_SOP_POP_32_S_10_12",	    	  /* name.  */
-	 false,			       		  /* partial_inplace.  */
+	 10,					  /* bitpos.  */
+	 complain_overflow_signed,		  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_10_12",		  /* name.  */
+	 false,					  /* partial_inplace.  */
 	 0,					  /* src_mask */
 	 0x3ffc00,				  /* dst_mask */
 	 false,					  /* pcrel_offset */
 	 BFD_RELOC_LARCH_SOP_POP_32_S_10_12,	  /* bfd_reloc_code_real_type */
-	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
+	 reloc_bits,				  /* adjust_reloc_bits */
+	 NULL),					  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16,	  /* type (41).  */
-	 0,				   	  /* rightshift.  */
-	 4,				   	  /* size.  */
-	 16,				  	  /* bitsize.  */
+	 0,					  /* rightshift.  */
+	 4,					  /* size.  */
+	 16,					  /* bitsize.  */
 	 false,					  /* pc_relative.  */
-	 10,				   	  /* bitpos.  */
-	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		  /* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_10_16",	    	  /* name.  */
-	 false,			       		  /* partial_inplace.  */
+	 10,					  /* bitpos.  */
+	 complain_overflow_signed,		  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_10_16",		  /* name.  */
+	 false,					  /* partial_inplace.  */
 	 0,					  /* src_mask */
 	 0x3fffc00,				  /* dst_mask */
 	 false,					  /* pcrel_offset */
 	 BFD_RELOC_LARCH_SOP_POP_32_S_10_16,	  /* bfd_reloc_code_real_type */
-	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
+	 reloc_bits,				  /* adjust_reloc_bits */
+	 NULL),					  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42).  */
 	 2,					  /* rightshift.  */
-	 4,				   	  /* size.  */
-	 16,				  	  /* bitsize.  */
+	 4,					  /* size.  */
+	 16,					  /* bitsize.  */
 	 false,					  /* pc_relative.  */
-	 10,				   	  /* bitpos.  */
-	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		  /* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_10_16_S2",    	  /* name.  */
-	 false,			       		  /* partial_inplace.  */
+	 10,					  /* bitpos.  */
+	 complain_overflow_signed,		  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_10_16_S2",	  /* name.  */
+	 false,					  /* partial_inplace.  */
 	 0,					  /* src_mask */
 	 0x3fffc00,				  /* dst_mask */
 	 false,					  /* pcrel_offset */
 	 BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2,	  /* bfd_reloc_code_real_type */
-	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
+	 reloc_bits_b16,			  /* adjust_reloc_bits */
+	 NULL),					  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20,	  /* type (43).  */
-	 0,				   	  /* rightshift.  */
-	 4,				   	  /* size.  */
-	 20,				  	  /* bitsize.  */
+	 0,					  /* rightshift.  */
+	 4,					  /* size.  */
+	 20,					  /* bitsize.  */
 	 false,					  /* pc_relative.  */
-	 5,				   	  /* bitpos.  */
-	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		  /* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_5_20",    	  /* name.  */
-	 false,			       		  /* partial_inplace.  */
+	 5,					  /* bitpos.  */
+	 complain_overflow_signed,		  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_5_20",		  /* name.  */
+	 false,					  /* partial_inplace.  */
 	 0,					  /* src_mask */
 	 0x1ffffe0,				  /* dst_mask */
 	 false,					  /* pcrel_offset */
 	 BFD_RELOC_LARCH_SOP_POP_32_S_5_20,	  /* bfd_reloc_code_real_type */
-	 loongarch_gen_adjust_reloc_bits),        /* adjust_reloc_bits */
+	 reloc_bits,				  /* adjust_reloc_bits */
+	 NULL),					  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2,
 						  /* type (44).  */
 	 2,					  /* rightshift.  */
 	 4,					  /* size.  */
-	 21,				  	  /* bitsize.  */
+	 21,					  /* bitsize.  */
 	 false,					  /* pc_relative.  */
-	 0,				   	  /* bitpos.  */
-	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		  /* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_0_5_10_16_S2",  	  /* name.  */
-	 false,			       		  /* partial_inplace.  */
+	 0,					  /* bitpos.  */
+	 complain_overflow_signed,		  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_0_5_10_16_S2",	  /* name.  */
+	 false,					  /* partial_inplace.  */
 	 0xfc0003e0,				  /* src_mask */
 	 0xfc0003e0,				  /* dst_mask */
 	 false,					  /* pcrel_offset */
 	 BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2,
 						  /* bfd_reloc_code_real_type */
-	 loongarch_adjust_reloc_bits_l16_xx5_h5), /* adjust_reloc_bits */
+	 reloc_bits_b21,			  /* adjust_reloc_bits */
+	 NULL),					  /* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2,	/* type (45).  */
-	 2,				   	/* rightshift.  */
-	 4,				   	/* size.  */
-	 26,				  	/* bitsize.  */
-	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_0_10_10_16_S2", 	/* name.  */
-	 false,			       		/* partial_inplace.  */
-	 0xfc000000,				/* src_mask */
-	 0xfc000000,				/* dst_mask */
+	 2,					/* rightshift.  */
+	 4,					/* size.  */
+	 26,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_0_10_10_16_S2",	/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x03ffffff,				/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2,
 						/* bfd_reloc_code_real_type */
-	 loongarch_adjust_reloc_bits_l16_h10),	/* adjust_reloc_bits */
+	 reloc_bits_b26,			/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U,	/* type (46).  */
-	 0,				   	/* rightshift.  */
-	 4,				   	/* size.  */
-	 32,				  	/* bitsize.  */
-	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_unsigned,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_U",    		/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 32,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_unsigned,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_U",		/* name.  */
+	 false,					/* partial_inplace.  */
 	 0xffffffff00000000,			/* src_mask */
 	 0x00000000ffffffff,			/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_SOP_POP_32_U,		/* bfd_reloc_code_real_type */
-	 loongarch_gen_adjust_reloc_bits),	/* adjust_reloc_bits */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_ADD8,	      	/* type (47).  */
-	 0,				   	/* rightshift.  */
-	 4,				   	/* size.  */
-	 8,				  	/* bitsize.  */
+  LOONGARCH_HOWTO (R_LARCH_ADD8,		/* type (47).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 8,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_ADD8",    			/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_ADD8",			/* name.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask */
 	 ALL_ONES,				/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_ADD8,			/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_ADD16,	      	/* type (48).  */
-	 0,				   	/* rightshift.  */
-	 4,				   	/* size.  */
-	 16,				  	/* bitsize.  */
+  LOONGARCH_HOWTO (R_LARCH_ADD16,		/* type (48).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 16,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_ADD16",    			/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_ADD16",			/* name.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask */
 	 ALL_ONES,				/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_ADD16,			/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_ADD24,	      	/* type (49).  */
-	 0,				   	/* rightshift.  */
-	 4,				   	/* size.  */
-	 24,				  	/* bitsize.  */
+  LOONGARCH_HOWTO (R_LARCH_ADD24,		/* type (49).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 24,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_ADD24",    			/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_ADD24",			/* name.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask */
 	 ALL_ONES,				/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_ADD24,			/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_ADD32,	      	/* type (50).  */
-	 0,				   	/* rightshift.  */
-	 4,				   	/* size.  */
-	 32,				  	/* bitsize.  */
+  LOONGARCH_HOWTO (R_LARCH_ADD32,		/* type (50).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 32,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_ADD32",    			/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_ADD32",			/* name.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask */
 	 ALL_ONES,				/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_ADD32,			/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_ADD64,	      	/* type (51).  */
-	 0,				   	/* rightshift.  */
-	 8,				   	/* size.  */
-	 64,				  	/* bitsize.  */
+  LOONGARCH_HOWTO (R_LARCH_ADD64,		/* type (51).  */
+	 0,					/* rightshift.  */
+	 8,					/* size.  */
+	 64,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_ADD64",    			/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_ADD64",			/* name.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask */
 	 ALL_ONES,				/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_ADD64,			/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_SUB8,	      	/* type (52).  */
-	 0,				   	/* rightshift.  */
-	 4,				   	/* size.  */
-	 8,				  	/* bitsize.  */
+  LOONGARCH_HOWTO (R_LARCH_SUB8,		/* type (52).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 8,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SUB8",    			/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_SUB8",			/* name.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask */
 	 ALL_ONES,				/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_SUB8,			/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_SUB16,	      	/* type (53).  */
-	 0,				   	/* rightshift.  */
-	 4,				   	/* size.  */
-	 16,				  	/* bitsize.  */
+  LOONGARCH_HOWTO (R_LARCH_SUB16,		/* type (53).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 16,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SUB16",    			/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_SUB16",			/* name.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask */
 	 ALL_ONES,				/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_SUB16,			/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_SUB24,	      	/* type (54).  */
-	 0,				   	/* rightshift.  */
-	 4,				   	/* size.  */
-	 24,				  	/* bitsize.  */
+  LOONGARCH_HOWTO (R_LARCH_SUB24,		/* type (54).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 24,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SUB24",    			/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_SUB24",			/* name.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask */
 	 ALL_ONES,				/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_SUB24,			/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_SUB32,	      	/* type (55).  */
-	 0,				   	/* rightshift.  */
-	 4,				   	/* size.  */
-	 32,				  	/* bitsize.  */
+  LOONGARCH_HOWTO (R_LARCH_SUB32,		/* type (55).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 32,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SUB32",    			/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_SUB32",			/* name.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask */
 	 ALL_ONES,				/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_SUB32,			/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_SUB64,	      	/* type (56).  */
-	 0,				   	/* rightshift.  */
-	 8,				   	/* size.  */
-	 64,				  	/* bitsize.  */
+  LOONGARCH_HOWTO (R_LARCH_SUB64,		/* type (56).  */
+	 0,					/* rightshift.  */
+	 8,					/* size.  */
+	 64,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SUB64",    			/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_SUB64",			/* name.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask */
 	 ALL_ONES,				/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_LARCH_SUB64,			/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT,      	/* type (57).  */
-	 0,				   	/* rightshift.  */
-	 0,				   	/* size.  */
-	 0,				  	/* bitsize.  */
+  LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT,	/* type (57).  */
+	 0,					/* rightshift.  */
+	 0,					/* size.  */
+	 0,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_GNU_VTINHERIT",  		/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_GNU_VTINHERIT",		/* name.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask */
 	 0,					/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_NONE,			/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY,      	/* type (58).  */
-	 0,				   	/* rightshift.  */
-	 0,				   	/* size.  */
-	 0,				  	/* bitsize.  */
+  LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY,		/* type (58).  */
+	 0,					/* rightshift.  */
+	 0,					/* size.  */
+	 0,					/* bitsize.  */
 	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
 	 NULL,					/* special_function.  */
-	 "R_LARCH_GNU_VTENTRY",  		/* name.  */
-	 false,			       		/* partial_inplace.  */
+	 "R_LARCH_GNU_VTENTRY",			/* name.  */
+	 false,					/* partial_inplace.  */
 	 0,					/* src_mask */
 	 0,					/* dst_mask */
 	 false,					/* pcrel_offset */
 	 BFD_RELOC_NONE,			/* bfd_reloc_code_real_type */
-	 NULL),					/* adjust_reloc_bits */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
+
+  LOONGARCH_EMPTY_HOWTO (59),
+  LOONGARCH_EMPTY_HOWTO (60),
+  LOONGARCH_EMPTY_HOWTO (61),
+  LOONGARCH_EMPTY_HOWTO (62),
+  LOONGARCH_EMPTY_HOWTO (63),
+
+  /* New reloc types.  */
+  LOONGARCH_HOWTO (R_LARCH_B16,			/* type (64).  */
+	 2,					/* rightshift.  */
+	 4,					/* size.  */
+	 16,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 10,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_B16",				/* name.  */
+	 false,					/* partial_inplace.  */
+	 0x3fffc00,				/* src_mask */
+	 0x3fffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_B16,			/* bfd_reloc_code_real_type */
+	 reloc_bits_b16,			/* adjust_reloc_bits */
+	 "b16"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_B21,			/* type (65).  */
+	 2,					/* rightshift.  */
+	 4,					/* size.  */
+	 21,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_B21",				/* name.  */
+	 false,					/* partial_inplace.  */
+	 0xfc0003e0,				/* src_mask */
+	 0xfc0003e0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_B21,			/* bfd_reloc_code_real_type */
+	 reloc_bits_b21,			/* adjust_reloc_bits */
+	 "b21"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_B26,			/* type (66).  */
+	 2,					/* rightshift.  */
+	 4,					/* size.  */
+	 26,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_B26",				/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x03ffffff,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_B26,			/* bfd_reloc_code_real_type */
+	 reloc_bits_b26,			/* adjust_reloc_bits */
+	 "b26"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_ABS_HI20,		/* type (67).  */
+	 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_ABS_HI20",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_ABS_HI20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "abs_hi20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_ABS_LO12,		/* type (68).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 12,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 10,					/* bitpos.  */
+	 complain_overflow_unsigned,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_ABS_LO12",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_ABS_LO12,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "abs_lo12"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_ABS64_LO20,		/* type (69).  */
+	 32,					/* rightshift.  */
+	 4,					/* size.  */
+	 20,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 5,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_ABS64_LO20",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_ABS64_LO20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "abs64_lo20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_ABS64_HI12,		/* type (70).  */
+	 52,					/* rightshift.  */
+	 4,					/* size.  */
+	 12,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 10,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_ABS64_HI12",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_ABS64_HI12,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "abs64_hi12"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_PCALA_HI20,		/* type (71).  */
+	 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_PCALA_HI20",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_PCALA_HI20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "pc_hi20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_PCALA_LO12,		/* type (72).  */
+	 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_PCALA_LO12",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_PCALA_LO12,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "pc_lo12"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_PCALA64_LO20,	/* type (73).  */
+	 32,					/* rightshift.  */
+	 4,					/* size.  */
+	 20,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 5,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_PCALA64_LO20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_PCALA64_LO20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "pc64_lo20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_PCALA64_HI12,	/* type (74).  */
+	 52,					/* rightshift.  */
+	 4,					/* size.  */
+	 12,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 10,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_PCALA64_HI12",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_PCALA64_HI12,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "pc64_hi12"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_GOT_PC_HI20,		/* type (75).  */
+	 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_GOT_PC_HI20",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_GOT_PC_HI20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "got_pc_hi20"),			/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_GOT_PC_LO12,		/* type (76).  */
+	 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_GOT_PC_LO12",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_GOT_PC_LO12,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "got_pc_lo12"),			/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_GOT64_PC_LO20,	/* type (77).  */
+	 32,					/* rightshift.  */
+	 4,					/* size.  */
+	 20,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 5,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_GOT64_PC_LO20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_GOT64_PC_LO20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "got64_pc_lo20"),			/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_GOT64_PC_HI12,	/* type (78).  */
+	 52,					/* rightshift.  */
+	 4,					/* size.  */
+	 12,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 10,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_GOT64_PC_HI12",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_GOT64_PC_HI12,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "got64_pc_hi12"),			/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_GOT64_HI20,		/* type (79).  */
+	 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_GOT64_HI20",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_GOT64_HI20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "got64_hi20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_GOT64_LO12,		/* type (80).  */
+	 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_GOT64_LO12",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_GOT64_LO12,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "got64_lo12"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_GOT64_LO20,		/* type (81).  */
+	 32,					/* rightshift.  */
+	 4,					/* size.  */
+	 20,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 5,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_GOT64_LO20",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_GOT64_LO20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "got64_lo20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_GOT64_HI12,		/* type (82).  */
+	 52,					/* rightshift.  */
+	 4,					/* size.  */
+	 12,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 10,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_GOT64_HI12",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_GOT64_HI12,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "got64_hi12"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_LE_HI20,		/* type (83).  */
+	 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",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_LE_HI20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "le_hi20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_LE_LO12,		/* type (84).  */
+	 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",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_LE_LO12,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "le_lo12"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_LE64_LO20,	/* type (85).  */
+	 32,					/* 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_LE64_LO20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_LE64_LO20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "le64_lo20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_LE64_HI12,	/* type (86).  */
+	 52,					/* 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_LE64_HI12",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_LE64_HI12,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "le64_hi12"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_HI20,	/* type (87).  */
+	 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_IE_PC_HI20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_IE_PC_HI20,	/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "ie_pc_hi20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_LO12,	/* type (88).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 12,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 10,					/* bitpos.  */
+	 complain_overflow_unsigned,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_TLS_IE_PC_LO12",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_IE_PC_LO12,	/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "ie_pc_lo12"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_LO20,	/* type (89).  */
+	 32,					/* 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_IE64_PC_LO20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_IE64_PC_LO20,	/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "ie64_pc_lo20"),			/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_HI12,	/* type (90).  */
+	 52,					/* 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_IE64_PC_HI12",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_IE64_PC_HI12,	/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "ie64_pc_hi12"),			/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_IE64_HI20,	/* type (91).  */
+	 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_IE64_HI20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_IE64_HI20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "ie64_hi20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_IE64_LO12,	/* type (92).  */
+	 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_IE64_LO12",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_IE64_LO12,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "ie64_lo12"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_IE64_LO20,	/* type (93).  */
+	 32,					/* 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_IE64_LO20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_IE64_LO20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "ie64_lo20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_IE64_HI12,	/* type (94).  */
+	 52,					/* 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_IE64_HI12",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x3ffc00,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_IE64_HI12,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "ie64_hi12"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_LD_PC_HI20,	/* type (95).  */
+	 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_LD_PC_HI20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_LD_PC_HI20,	/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "ld_pc_hi20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_LD64_HI20,	/* type (96).  */
+	 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_LD64_HI20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_LD64_HI20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "ld64_hi20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_GD_PC_HI20,	/* type (97).  */
+	 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_GD_PC_HI20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_GD_PC_HI20,	/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "gd_pc_hi20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_GD64_HI20,	/* type (98).  */
+	 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_GD64_HI20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0x1ffffe0,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_GD64_HI20,		/* bfd_reloc_code_real_type */
+	 reloc_bits,				/* adjust_reloc_bits */
+	 "gd64_hi20"),				/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_RELAX,		/* type (99).  */
+	 0,					/* rightshift */
+	 1,					/* size */
+	 0,					/* bitsize */
+	 false,					/* pc_relative */
+	 0,					/* bitpos */
+	 complain_overflow_dont,		/* complain_on_overflow */
+	 bfd_elf_generic_reloc,			/* special_function */
+	 "R_LARCH_RELAX",			/* name */
+	 false,					/* partial_inplace */
+	 0,					/* src_mask */
+	 0,					/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_RELAX,			/* bfd_reloc_code_real_type */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
+
 };
 
 reloc_howto_type *
@@ -697,8 +1357,6 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
       if (loongarch_howto_table[r_type].howto.type == r_type)
 	return (reloc_howto_type *)&loongarch_howto_table[r_type];
 
-      BFD_ASSERT (loongarch_howto_table[r_type].howto.type == r_type);
-
       for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
 	if (loongarch_howto_table[i].howto.type == r_type)
 	  return (reloc_howto_type *)&loongarch_howto_table[i];
@@ -734,6 +1392,17 @@ loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 {
   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)
+    {
+      BFD_ASSERT (BFD_RELOC_LARCH_RELAX - BFD_RELOC_LARCH_B16
+		  == R_LARCH_RELAX - R_LARCH_B16);
+      loongarch_reloc_howto_type *ht = NULL;
+      ht = &loongarch_howto_table[code - BFD_RELOC_LARCH_B16 + R_LARCH_B16];
+      BFD_ASSERT (ht->bfd_type == code);
+      return (reloc_howto_type *)ht;
+    }
+
   for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
     if (loongarch_howto_table[i].bfd_type == code)
       return (reloc_howto_type *)&loongarch_howto_table[i];
@@ -745,56 +1414,89 @@ loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return NULL;
 }
 
+bfd_reloc_code_real_type
+loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+				   const char *l_r_name)
+{
+  for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
+    {
+      loongarch_reloc_howto_type *lht = &loongarch_howto_table[i];
+      if ((NULL != lht->larch_reloc_type_name)
+	  && (0 == strcmp (lht->larch_reloc_type_name, l_r_name)))
+	return lht->bfd_type;
+    }
+
+  (*_bfd_error_handler) (_("%pB: unsupported relocation type name %s"),
+			 abfd, l_r_name);
+  bfd_set_error (bfd_error_bad_value);
+  return BFD_RELOC_NONE;
+}
+
+
+/* Functions for reloc bits field.
+   1.  Signed extend *fix_val.
+   2.  Return false if overflow.  */
+
 #define LARCH_RELOC_BFD_VMA_BIT_MASK(bitsize) \
   (~((((bfd_vma)0x1) << (bitsize)) - 1))
 
 /* Adjust val to perform insn
- * BFD_RELOC_LARCH_SOP_POP_32_S_10_5
- * BFD_RELOC_LARCH_SOP_POP_32_S_10_12
- * BFD_RELOC_LARCH_SOP_POP_32_U_10_12
- * BFD_RELOC_LARCH_SOP_POP_32_S_10_16
- * BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2
- * BFD_RELOC_LARCH_SOP_POP_32_S_5_20
- * BFD_RELOC_LARCH_SOP_POP_32_U.
-*/
-
-bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val)
+   BFD_RELOC_LARCH_SOP_POP_32_S_10_5
+   BFD_RELOC_LARCH_SOP_POP_32_S_10_12
+   BFD_RELOC_LARCH_SOP_POP_32_U_10_12
+   BFD_RELOC_LARCH_SOP_POP_32_S_10_16
+   BFD_RELOC_LARCH_SOP_POP_32_S_5_20
+   BFD_RELOC_LARCH_SOP_POP_32_U.  */
+static bool
+reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val)
 {
-  bfd_vma val = *fix_val;
-  /* Check val low bits if rightshift != 0, before rightshift  */
-  if (howto->rightshift
-      && (((0x1UL << howto->rightshift) - 1) & val))
+  bfd_signed_vma val = ((bfd_signed_vma)(*fix_val)) >> howto->rightshift;
+
+  /* Perform insn bits field.  */
+  val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
+  val <<= howto->bitpos;
+
+  *fix_val = (bfd_vma)val;
+
+  return true;
+}
+
+/* Adjust val to perform insn
+   R_LARCH_SOP_POP_32_S_10_16_S2
+   R_LARCH_B16.  */
+static bool
+reloc_bits_b16 (reloc_howto_type *howto, bfd_vma *fix_val)
+{
+  if (howto->complain_on_overflow != complain_overflow_signed)
+    return false;
+
+  bfd_signed_vma val = *fix_val;
+
+  /* Judge whether 4 bytes align.  */
+  if (val & ((0x1UL << howto->rightshift) - 1))
     return false;
 
   int bitsize = howto->bitsize + howto->rightshift;
+  bfd_signed_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
 
-  /* Return false if overflow.  */
-  if (howto->complain_on_overflow == complain_overflow_signed)
+  /* If val < 0, sign bit is 1.  */
+  if (sig_bit)
     {
-      bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
-      /* If val < 0.  */
-      if (sig_bit)
-	{
-	  if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
-	      != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
-	    return false;
-	}
-      else
-	{
-	  if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
-	    return false;
-	}
+      /* Signed bits is 1.  */
+      if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
+	  != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
+	return false;
     }
-  else if (howto->complain_on_overflow == complain_overflow_unsigned)
+  else
     {
+      /* Signed bits is 0.  */
       if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val)
 	return false;
     }
-  else
-    return false;
 
   /* Perform insn bits field.  */
-  val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
+  val >>= howto->rightshift;
+  val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
   val <<= howto->bitpos;
 
   *fix_val = val;
@@ -802,22 +1504,24 @@ bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val)
   return true;
 }
 
-/* Reloc type R_LARCH_SOP_POP_32_S_0_5_10_16_S2.  */
-bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
-					     bfd_vma *fix_val)
+/* Reloc type :
+   R_LARCH_SOP_POP_32_S_0_5_10_16_S2
+   R_LARCH_B21.  */
+static bool
+reloc_bits_b21 (reloc_howto_type *howto,
+		bfd_vma *fix_val)
 {
-  bfd_vma val = *fix_val;
-  /* Check val low bits if rightshift != 0, before rightshift  */
-  if (howto->rightshift
-      && (((0x1UL << howto->rightshift) - 1) & val))
+  if (howto->complain_on_overflow != complain_overflow_signed)
     return false;
 
-  /* Return false if overflow.  */
-  if (howto->complain_on_overflow != complain_overflow_signed)
+  bfd_signed_vma val = *fix_val;
+
+  if (val & ((0x1UL << howto->rightshift) - 1))
     return false;
 
   int bitsize = howto->bitsize + howto->rightshift;
-  bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
+  bfd_signed_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
+
   /* If val < 0.  */
   if (sig_bit)
     {
@@ -827,14 +1531,15 @@ bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
     }
   else
     {
-      if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
+      if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val)
 	return false;
     }
 
   /* Perform insn bits field.  */
-  val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
+  val >>= howto->rightshift;
+  val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
 
-  /* Perform insn bits field. 20:16>>16, 15:0<<10 */
+  /* Perform insn bits field.  15:0<<10, 20:16>>16.  */
   val = ((val & 0xffff) << 10) | ((val >> 16) & 0x1f);
 
   *fix_val = val;
@@ -842,22 +1547,25 @@ bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
   return true;
 }
 
-/* Reloc type R_LARCH_SOP_POP_32_S_0_10_10_16_S2.  */
-bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
-					  bfd_vma *fix_val)
+/* Reloc type:
+   R_LARCH_SOP_POP_32_S_0_10_10_16_S2
+   R_LARCH_B26.  */
+static bool
+reloc_bits_b26 (reloc_howto_type *howto,
+		bfd_vma *fix_val)
 {
-  bfd_vma val = *fix_val;
-  /* Check val low bits if rightshift != 0, before rightshift  */
-  if (howto->rightshift
-      && (((0x1UL << howto->rightshift) - 1) & val))
-    return false;
-
   /* Return false if overflow.  */
   if (howto->complain_on_overflow != complain_overflow_signed)
     return false;
 
+  bfd_signed_vma val = *fix_val;
+
+  if (val & ((0x1UL << howto->rightshift) - 1))
+    return false;
+
   int bitsize = howto->bitsize + howto->rightshift;
-  bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
+  bfd_signed_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
+
   /* If val < 0.  */
   if (sig_bit)
     {
@@ -867,14 +1575,15 @@ bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
     }
   else
     {
-      if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
+      if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val)
 	return false;
     }
 
   /* Perform insn bits field.  */
-  val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
+  val >>= howto->rightshift;
+  val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
 
-  /* Perform insn bits field. 25:16>>16, 15:0<<10 */
+  /* Perform insn bits field.  25:16>>16, 15:0<<10.  */
   val = ((val & 0xffff) << 10) | ((val >> 16) & 0x3ff);
 
   *fix_val = val;
@@ -882,8 +1591,9 @@ bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
   return true;
 }
 
-bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto,
-				       bfd_vma *fix_val)
+bool
+loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto,
+				  bfd_vma *fix_val)
 {
   BFD_ASSERT (((loongarch_reloc_howto_type *)howto)->adjust_reloc_bits);
   return ((loongarch_reloc_howto_type *)
diff --git a/bfd/elfxx-loongarch.h b/bfd/elfxx-loongarch.h
index 8ea63d03fa5..7b8a72130f1 100644
--- a/bfd/elfxx-loongarch.h
+++ b/bfd/elfxx-loongarch.h
@@ -30,6 +30,10 @@ loongarch_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code);
 extern reloc_howto_type *
 loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name);
 
+extern bfd_reloc_code_real_type
+loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+				   const char *l_r_name);
+
 bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto, bfd_vma *fix_val);
 
 /* TRUE if this is a PLT reference to a local IFUNC.  */
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 29e8187f95f..b23ae4b755c 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -3457,6 +3457,42 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_LARCH_SUB24",
   "BFD_RELOC_LARCH_SUB32",
   "BFD_RELOC_LARCH_SUB64",
+  "BFD_RELOC_LARCH_B16",
+  "BFD_RELOC_LARCH_B21",
+  "BFD_RELOC_LARCH_B26",
+  "BFD_RELOC_LARCH_ABS_HI20",
+  "BFD_RELOC_LARCH_ABS_LO12",
+  "BFD_RELOC_LARCH_ABS64_LO20",
+  "BFD_RELOC_LARCH_ABS64_HI12",
+  "BFD_RELOC_LARCH_PCALA_HI20",
+  "BFD_RELOC_LARCH_PCALA_LO12",
+  "BFD_RELOC_LARCH_PCALA64_LO20",
+  "BFD_RELOC_LARCH_PCALA64_HI12",
+  "BFD_RELOC_LARCH_GOT_PC_HI20",
+  "BFD_RELOC_LARCH_GOT_PC_LO12",
+  "BFD_RELOC_LARCH_GOT64_PC_LO20",
+  "BFD_RELOC_LARCH_GOT64_PC_HI12",
+  "BFD_RELOC_LARCH_GOT64_HI20",
+  "BFD_RELOC_LARCH_GOT64_LO12",
+  "BFD_RELOC_LARCH_GOT64_LO20",
+  "BFD_RELOC_LARCH_GOT64_HI12",
+  "BFD_RELOC_LARCH_TLS_LE_HI20",
+  "BFD_RELOC_LARCH_TLS_LE_LO12",
+  "BFD_RELOC_LARCH_TLS_LE64_LO20",
+  "BFD_RELOC_LARCH_TLS_LE64_HI12",
+  "BFD_RELOC_LARCH_TLS_IE_PC_HI20",
+  "BFD_RELOC_LARCH_TLS_IE_PC_LO12",
+  "BFD_RELOC_LARCH_TLS_IE64_PC_LO20",
+  "BFD_RELOC_LARCH_TLS_IE64_PC_HI12",
+  "BFD_RELOC_LARCH_TLS_IE64_HI20",
+  "BFD_RELOC_LARCH_TLS_IE64_LO12",
+  "BFD_RELOC_LARCH_TLS_IE64_LO20",
+  "BFD_RELOC_LARCH_TLS_IE64_HI12",
+  "BFD_RELOC_LARCH_TLS_LD_PC_HI20",
+  "BFD_RELOC_LARCH_TLS_LD64_HI20",
+  "BFD_RELOC_LARCH_TLS_GD_PC_HI20",
+  "BFD_RELOC_LARCH_TLS_GD64_HI20",
+  "BFD_RELOC_LARCH_RELAX",
  "@@overflow: BFD_RELOC_UNUSED@@",
 };
 #endif
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 36999fe9a40..836fa162108 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -8228,6 +8228,85 @@ ENUMX
   BFD_RELOC_LARCH_SUB32
 ENUMX
   BFD_RELOC_LARCH_SUB64
+
+ENUMX
+  BFD_RELOC_LARCH_B16
+ENUMX
+  BFD_RELOC_LARCH_B21
+ENUMX
+  BFD_RELOC_LARCH_B26
+
+ENUMX
+  BFD_RELOC_LARCH_ABS_HI20
+ENUMX
+  BFD_RELOC_LARCH_ABS_LO12
+ENUMX
+  BFD_RELOC_LARCH_ABS64_LO20
+ENUMX
+  BFD_RELOC_LARCH_ABS64_HI12
+
+ENUMX
+  BFD_RELOC_LARCH_PCALA_HI20
+ENUMX
+  BFD_RELOC_LARCH_PCALA_LO12
+ENUMX
+  BFD_RELOC_LARCH_PCALA64_LO20
+ENUMX
+  BFD_RELOC_LARCH_PCALA64_HI12
+
+ENUMX
+  BFD_RELOC_LARCH_GOT_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_GOT_PC_LO12
+ENUMX
+  BFD_RELOC_LARCH_GOT64_PC_LO20
+ENUMX
+  BFD_RELOC_LARCH_GOT64_PC_HI12
+ENUMX
+  BFD_RELOC_LARCH_GOT64_HI20
+ENUMX
+  BFD_RELOC_LARCH_GOT64_LO12
+ENUMX
+  BFD_RELOC_LARCH_GOT64_LO20
+ENUMX
+  BFD_RELOC_LARCH_GOT64_HI12
+
+ENUMX
+  BFD_RELOC_LARCH_TLS_LE_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_LE_LO12
+ENUMX
+  BFD_RELOC_LARCH_TLS_LE64_LO20
+ENUMX
+  BFD_RELOC_LARCH_TLS_LE64_HI12
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE_PC_LO12
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_PC_LO20
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_PC_HI12
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_LO12
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_LO20
+ENUMX
+  BFD_RELOC_LARCH_TLS_IE64_HI12
+ENUMX
+  BFD_RELOC_LARCH_TLS_LD_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_LD64_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_GD_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_GD64_HI20
+
+ENUMX
+  BFD_RELOC_LARCH_RELAX
+
 ENUMDOC
   LARCH relocations.
 
diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h
index b7aa4ff069c..863dad3a371 100644
--- a/include/elf/loongarch.h
+++ b/include/elf/loongarch.h
@@ -90,6 +90,142 @@ RELOC_NUMBER (R_LARCH_SUB64, 56)
 RELOC_NUMBER (R_LARCH_GNU_VTINHERIT, 57)
 RELOC_NUMBER (R_LARCH_GNU_VTENTRY, 58)
 
+
+/* B16:
+   beq/bne/blt/bge/bltu/bgeu/jirl
+   %b16 (sym).  */
+RELOC_NUMBER (R_LARCH_B16, 64)
+/* B21:
+   beqz/bnez
+   %b16 (sym).  */
+RELOC_NUMBER (R_LARCH_B21, 65)
+/* B26:
+   b/bl
+   %b26 (sym) or %plt (sym).  */
+RELOC_NUMBER (R_LARCH_B26, 66)
+
+/* ABS: 32/64
+   lu12i.w
+   %abs_hi20 (sym).  */
+RELOC_NUMBER (R_LARCH_ABS_HI20, 67)
+/* ABS: 32/64
+   ori
+   %abs_lo12 (sym).  */
+RELOC_NUMBER (R_LARCH_ABS_LO12, 68)
+
+/* ABS: 64
+   lu32i.d
+   %abs64_lo20 (sym).  */
+RELOC_NUMBER (R_LARCH_ABS64_LO20, 69)
+/* ABS: 64
+   lu52i.d
+   %abs64_hi12 (sym).  */
+RELOC_NUMBER (R_LARCH_ABS64_HI12, 70)
+
+/* PCREL: 32/64
+   pcalau12i
+   %pc_hi20 (sym).  */
+RELOC_NUMBER (R_LARCH_PCALA_HI20, 71)
+/* PCREL: 32/64
+   addi.w/addi.d
+   %pc_lo12 (sym).  */
+RELOC_NUMBER (R_LARCH_PCALA_LO12, 72)
+/* PCREL: 64
+   lu32i.d
+   %pc64_lo20 (sym).  */
+RELOC_NUMBER (R_LARCH_PCALA64_LO20, 73)
+/* PCREL: 64
+   lu52i.d
+   %pc64_hi12 (sym).  */
+RELOC_NUMBER (R_LARCH_PCALA64_HI12, 74)
+
+/* GOT: 32/64
+   pcalau12i
+   %got_pc_hi20 (got).  */
+RELOC_NUMBER (R_LARCH_GOT_PC_HI20, 75)
+/* GOT: 32/64
+   ld.w/ld.d
+   %got_pc_lo12 (got).  */
+RELOC_NUMBER (R_LARCH_GOT_PC_LO12, 76)
+/* GOT: 32/64
+   lu32i.d
+   %got_pc_lo12 (got).  */
+RELOC_NUMBER (R_LARCH_GOT64_PC_LO20, 77)
+/* GOT64: PCREL
+   lu52i.d
+   %got64_pc_hi12 (got).  */
+RELOC_NUMBER (R_LARCH_GOT64_PC_HI12, 78)
+/* GOT64: ABS
+   lu12i.w
+   %got64_hi20 (got).  */
+RELOC_NUMBER (R_LARCH_GOT64_HI20, 79)
+/* GOT64: ABS
+   ori
+   %got64_lo12 (got).  */
+RELOC_NUMBER (R_LARCH_GOT64_LO12, 80)
+/* GOT64: ABS
+   lu32i.d
+   %got64_lo20 (got).  */
+RELOC_NUMBER (R_LARCH_GOT64_LO20, 81)
+/* GOT64: ABS
+   lu52i.d
+   %got64_hi12 (got).  */
+RELOC_NUMBER (R_LARCH_GOT64_HI12, 82)
+
+/* TLS-LE: 32/64
+   lu12i.w
+   %le_hi20 (sym).  */
+RELOC_NUMBER (R_LARCH_TLS_LE_HI20, 83)
+/* TLS-LE: 32/64
+   ori
+   %le_lo12 (sym).  */
+RELOC_NUMBER (R_LARCH_TLS_LE_LO12, 84)
+/* TLS-LE: 64
+   lu32i.d
+   %le64_lo20 (sym).  */
+RELOC_NUMBER (R_LARCH_TLS_LE64_LO20, 85)
+/* TLS-LE: 64
+   lu52i.d
+   %le64_hi12 (sym).  */
+RELOC_NUMBER (R_LARCH_TLS_LE64_HI12, 86)
+
+/* TLS-IE: 32/64
+   pcalau12i
+   %ie_pc_hi20 (sym).  */
+RELOC_NUMBER (R_LARCH_TLS_IE_PC_HI20, 87)
+RELOC_NUMBER (R_LARCH_TLS_IE_PC_LO12, 88)
+RELOC_NUMBER (R_LARCH_TLS_IE64_PC_LO20, 89)
+RELOC_NUMBER (R_LARCH_TLS_IE64_PC_HI12, 90)
+
+/* TLS-IE64: ABS
+   lu12i.w
+   %ie64_hi20 (sym).  */
+RELOC_NUMBER (R_LARCH_TLS_IE64_HI20, 91)
+RELOC_NUMBER (R_LARCH_TLS_IE64_LO12, 92)
+RELOC_NUMBER (R_LARCH_TLS_IE64_LO20, 93)
+RELOC_NUMBER (R_LARCH_TLS_IE64_HI12, 94)
+
+/* TLS-LD: 32/64
+   pcalau12i
+   %ld_pc_hi20 (sym).  */
+RELOC_NUMBER (R_LARCH_TLS_LD_PC_HI20, 95)
+/* TLS-LD64: ABS
+   lu12i.w
+   %ld64_hi20 (sym).  */
+RELOC_NUMBER (R_LARCH_TLS_LD64_HI20, 96)
+
+/* TLS-GD: 32/64
+   pcalau12i
+   %gd_pc_hi20 (sym).  */
+RELOC_NUMBER (R_LARCH_TLS_GD_PC_HI20, 97)
+/* TLS-GD64: ABS
+   lu12i.w
+   %gd64_hi20 (sym).  */
+RELOC_NUMBER (R_LARCH_TLS_GD64_HI20, 98)
+
+/* RELAX.  */
+RELOC_NUMBER (R_LARCH_RELAX, 99)
+
 END_RELOC_NUMBERS (R_LARCH_count)
 
 /* Processor specific flags for the ELF header e_flags field.  */
@@ -102,9 +238,9 @@ END_RELOC_NUMBERS (R_LARCH_count)
 #define EF_LOONGARCH_ABI_ILP32_SINGLE_FLOAT	0x6
 #define EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT	0x7
 
-#define EF_LOONGARCH_ABI_MASK	    		0x7
-#define EF_LOONGARCH_ABI_ILP32_MASK	    	0x4
-#define EF_LOONGARCH_ABI_FLOAT_MASK	    	0x3
+#define EF_LOONGARCH_ABI_MASK			0x7
+#define EF_LOONGARCH_ABI_ILP32_MASK		0x4
+#define EF_LOONGARCH_ABI_FLOAT_MASK		0x3
 #define EF_LOONGARCH_ABI_SOFT_FLOAT_MASK	0x1
 #define EF_LOONGARCH_ABI_SINGLE_FLOAT_MASK	0x2
 #define EF_LOONGARCH_ABI_DOUBLE_FLOAT_MASK	0x3
-- 
2.31.1


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 2/5 v1] LoongArch:opcodes: Add new reloc types.
  2022-07-18  8:43 [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types liuzhensong
@ 2022-07-18  8:43 ` liuzhensong
  2022-07-18  8:43 ` [PATCH 3/5 v1] LoongArch: gas: " liuzhensong
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 24+ messages in thread
From: liuzhensong @ 2022-07-18  8:43 UTC (permalink / raw)
  To: binutils; +Cc: xuchenghua, mengqinggang, liuzhensong

  opcodes: Replace old insns with news and generate new relocate types
  while macro insns expanding.

  opcodes/
    loongarch-opc.c
---
 opcodes/loongarch-opc.c | 387 ++++++++++++++++++++++------------------
 1 file changed, 217 insertions(+), 170 deletions(-)

diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c
index 62a2edb1ca9..1c7dd2e8ee9 100644
--- a/opcodes/loongarch-opc.c
+++ b/opcodes/loongarch-opc.c
@@ -103,158 +103,205 @@ const char *const loongarch_x_normal_name[32] =
   "$xr24", "$xr25", "$xr26", "$xr27", "$xr28", "$xr29", "$xr30", "$xr31",
 };
 
+/* Can not use xx_pa for abs.  */
+
+/* For LoongArch32 abs.  */
+#define INSN_LA_ABS32		    \
+  "lu12i.w %1,%%abs_hi20(%2);"	    \
+  "ori %1,%1,%%abs_lo12(%2);",	    \
+  &LARCH_opts.ase_ilp32,	    \
+  &LARCH_opts.ase_lp64
+#define INSN_LA_ABS64			\
+  "lu12i.w %1,%%abs_hi20(%2);"		\
+  "ori %1,%1,%%abs_lo12(%2);"		\
+  "lu32i.d %1,%%abs64_lo20(%2);"	\
+  "lu52i.d %1,%1,%%abs64_hi12(%2);",	\
+  &LARCH_opts.ase_lp64, 0
+
+#define INSN_LA_PCREL32		    \
+  "pcalau12i %1,%%pc_hi20(%2);"	    \
+  "addi.w %1,%1,%%pc_lo12(%2);",    \
+  &LARCH_opts.ase_ilp32,	    \
+  &LARCH_opts.ase_lp64
+#define INSN_LA_PCREL64		    \
+  "pcalau12i %1,%%pc_hi20(%2);"	    \
+  "addi.d %1,%1,%%pc_lo12(%2);",    \
+  &LARCH_opts.ase_lp64, 0
+#define INSN_LA_PCREL64_LARGE	    \
+  "pcalau12i %1,%%pc_hi20(%3);"	    \
+  "addi.d %2,$r0,%%pc_lo12(%3);"    \
+  "lu32i.d %2,%%pc64_lo20(%3);"	    \
+  "lu52i.d %2,%2,%%pc64_hi12(%3);"  \
+  "add.d %1,%1,%2;",		    \
+  &LARCH_opts.ase_lp64, 0
+
+#define INSN_LA_GOT32		    \
+  "pcalau12i %1,%%got_pc_hi20(%2);" \
+  "ld.w %1,%1,%%got_pc_lo12(%2);",  \
+  &LARCH_opts.ase_ilp32,	    \
+  &LARCH_opts.ase_lp64
+#define INSN_LA_GOT64		    \
+  "pcalau12i %1,%%got_pc_hi20(%2);" \
+  "ld.d %1,%1,%%got_pc_lo12(%2);",  \
+  &LARCH_opts.ase_lp64, 0
+/* got64 abs.  */
+#define INSN_LA_GOT64_LARGE_ABS	    \
+  "lu12i.w %1,%%got64_hi20(%2);"    \
+  "ori %1,%1,%%got64_lo12(%2);"	    \
+  "lu32i.d %1,%%got64_lo20(%2);"    \
+  "lu52i.d %1,%1,%%got64_hi12(%2);" \
+  "ld.d %1,%1,0",		    \
+  &LARCH_opts.ase_lp64,		    \
+  &LARCH_opts.ase_gpcr
+/* got64 pic.  */
+#define INSN_LA_GOT64_LARGE_PCREL     \
+  "pcalau12i %1,%%got_pc_hi20(%3);"   \
+  "addi.d %2,$r0,%%got_pc_lo12(%3);"  \
+  "lu32i.d %2,%%got64_pc_lo20(%3);"   \
+  "lu52i.d %2,%2,%%got64_pc_hi12(%3);"\
+  "ldx.d %1,%1,%2;",		      \
+  &LARCH_opts.ase_lp64,		      \
+  &LARCH_opts.ase_gabs
+
+/* For LoongArch32/64 cmode=normal.  */
+#define INSN_LA_TLS_LE		    \
+  "lu12i.w %1,%%le_hi20(%2);"	    \
+  "ori %1,%1,%%le_lo12(%2);",	    \
+  &LARCH_opts.ase_ilp32, 0
+
+/* For LoongArch64 cmode=large.  */
+#define INSN_LA_TLS_LE64_LARGE	    \
+  "lu12i.w %1,%%le_hi20(%2);"	    \
+  "ori %1,%1,%%le_lo12(%2);"	    \
+  "lu32i.d %1,%%le64_lo20(%2);"	    \
+  "lu52i.d %1,%1,%%le64_hi12(%2);", \
+  &LARCH_opts.ase_lp64, 0
+
+#define INSN_LA_TLS_IE32	    \
+  "pcalau12i %1,%%ie_pc_hi20(%2);"  \
+  "ld.w %1,%1,%%ie_pc_lo12(%2);",  \
+  &LARCH_opts.ase_ilp32,	    \
+  &LARCH_opts.ase_lp64
+
+#define INSN_LA_TLS_IE64	    \
+  "pcalau12i %1,%%ie_pc_hi20(%2);"  \
+  "ld.d %1,%1,%%ie_pc_lo12(%2);",  \
+  &LARCH_opts.ase_lp64, 0
+
+/* For ie64 pic.  */
+#define INSN_LA_TLS_IE64_LARGE_PCREL  \
+  "pcalau12i %1,%%ie_pc_hi20(%3);"    \
+  "addi.d %2,$r0,%%ie_pc_lo12(%3);"  \
+  "lu32i.d %2,%%ie64_pc_lo20(%3);"   \
+  "lu52i.d %2,%2,%%ie64_pc_hi12(%3);"\
+  "ldx.d %1,%1,%2;",		      \
+  &LARCH_opts.ase_lp64,		      \
+  &LARCH_opts.ase_gabs
+
+/* For ie64 abs.  */
+#define INSN_LA_TLS_IE64_LARGE_ABS  \
+  "lu12i.w %1,%%ie64_hi20(%2);"	    \
+  "ori %1,%1,%%ie64_lo12(%2);"	    \
+  "lu32i.d %1,%%ie64_lo20(%2);"    \
+  "lu52i.d %1,%1,%%ie64_hi12(%2);" \
+  "ld.d %1,%1,0",		    \
+  &LARCH_opts.ase_lp64,		    \
+  &LARCH_opts.ase_gpcr
+
+/* For LoongArch32/64 cmode=normal.  */
+#define INSN_LA_TLS_LD32	      \
+  "pcalau12i %1,%%ld_pc_hi20(%2);"    \
+  "addi.w %1,%1,%%got_pc_lo12(%2);",  \
+  &LARCH_opts.ase_ilp32,	      \
+  &LARCH_opts.ase_lp64
+#define INSN_LA_TLS_LD64	      \
+  "pcalau12i %1,%%ld_pc_hi20(%2);"    \
+  "addi.d %1,%1,%%got_pc_lo12(%2);",  \
+  &LARCH_opts.ase_lp64, 0
+#define INSN_LA_TLS_LD64_LARGE_PCREL  \
+  "pcalau12i %1,%%ld_pc_hi20(%3);"    \
+  "addi.d %2,$r0,%%got_pc_lo12(%3);"  \
+  "lu32i.d %2,%%got64_pc_lo20(%3);"   \
+  "lu52i.d %2,%2,%%got64_pc_hi12(%3);"\
+  "add.d %1,%1,%2;",		      \
+  &LARCH_opts.ase_lp64,		      \
+  &LARCH_opts.ase_gabs
+#define INSN_LA_TLS_LD64_LARGE_ABS    \
+  "lu12i.w %1,%%ld64_hi20(%2);"	      \
+  "ori %1,%1,%%got64_lo12(%2);"	      \
+  "lu32i.d %1,%%got64_lo20(%2);"      \
+  "lu52i.d %1,%1,%%got64_hi12(%2);",  \
+  &LARCH_opts.ase_lp64,		      \
+  &LARCH_opts.ase_gpcr
+
+#define INSN_LA_TLS_GD32	      \
+  "pcalau12i %1,%%gd_pc_hi20(%2);"    \
+  "addi.w %1,%1,%%got_pc_lo12(%2);",  \
+  &LARCH_opts.ase_ilp32,	      \
+  &LARCH_opts.ase_lp64
+#define INSN_LA_TLS_GD64	      \
+  "pcalau12i %1,%%gd_pc_hi20(%2);"    \
+  "addi.d %1,%1,%%got_pc_lo12(%2);",  \
+  &LARCH_opts.ase_lp64, 0
+#define INSN_LA_TLS_GD64_LARGE_PCREL  \
+  "pcalau12i %1,%%gd_pc_hi20(%3);"  \
+  "addi.d %2,$r0,%%got_pc_lo12(%3);"  \
+  "lu32i.d %2,%%got64_pc_lo20(%3);"   \
+  "lu52i.d %2,%2,%%got64_pc_hi12(%3);"\
+  "add.d %1,%1,%2;",		      \
+  &LARCH_opts.ase_lp64,		      \
+  &LARCH_opts.ase_gabs
+#define INSN_LA_TLS_GD64_LARGE_ABS    \
+  "lu12i.w %1,%%gd64_hi20(%2);"	      \
+  "ori %1,%1,%%got64_lo12(%2);"	      \
+  "lu32i.d %1,%%got64_lo20(%2);"      \
+  "lu52i.d %1,%1,%%got64_hi12(%2);",  \
+  &LARCH_opts.ase_lp64,		      \
+  &LARCH_opts.ase_gpcr
+
+
 static struct loongarch_opcode loongarch_macro_opcodes[] =
 {
-  /* match,    mask,       name, format, macro, include, exclude, pinfo.  */
-  { 0, 0, "li.w", "r,sc", "%f", 0, 0, 0},
-  { 0, 0, "li.d", "r,sc", "%f", 0, 0, 0},
-  { 0, 0, "la", "r,la", "la.global %1,%2", 0, 0, 0 },
-
-  { 0, 0, "la.global", "r,la", "la.pcrel %1,%2",
-    &LARCH_opts.ase_gpcr, 0, 0 },
-  { 0, 0, "la.global", "r,r,la", "la.pcrel %1,%2,%3",
-    &LARCH_opts.ase_gpcr, 0, 0 },
-  { 0, 0, "la.global", "r,la", "la.abs %1,%2",
-    &LARCH_opts.ase_gabs, 0, 0 },
-  { 0, 0, "la.global", "r,r,la", "la.abs %1,%3",
-    &LARCH_opts.ase_gabs, 0, 0 },
-  { 0, 0, "la.global", "r,l", "la.got %1,%2", 0, 0, 0 },
-  { 0, 0, "la.global", "r,r,l", "la.got %1,%2,%3", 0, 0, 0 },
-
-  { 0, 0, "la.local", "r,la", "la.abs %1,%2",
-    &LARCH_opts.ase_labs, 0, 0 },
-  { 0, 0, "la.local", "r,r,la", "la.abs %1,%3",
-    &LARCH_opts.ase_labs, 0, 0 },
-  { 0, 0, "la.local", "r,la", "la.pcrel %1,%2", 0, 0, 0 },
-  { 0, 0, "la.local", "r,r,la", "la.pcrel %1,%2,%3", 0, 0, 0 },
-
-  { 0, 0, "la.abs", "r,la",
-    "lu12i.w %1,%%abs(%2)>>12;"
-    "ori %1,%1,%%abs(%2)&0xfff;",
-    &LARCH_opts.ase_ilp32, &LARCH_opts.ase_lp64, 0 },
-  { 0, 0, "la.abs", "r,la",
-    "lu12i.w %1,%%abs(%2)<<32>>44;"
-    "ori %1,%1,%%abs(%2)&0xfff;"
-    "lu32i.d %1,%%abs(%2)<<12>>44;"
-    "lu52i.d %1,%1,%%abs(%2)>>52;",
-    &LARCH_opts.ase_lp64, 0, 0 },
-
-  { 0, 0, "la.pcrel", "r,la",
-    "pcaddu12i %1,%%pcrel(%2+0x800)<<32>>44;"
-    "addi.w %1,%1,%%pcrel(%2+4)-(%%pcrel(%2+4+0x800)>>12<<12);",
-    &LARCH_opts.ase_ilp32, &LARCH_opts.ase_lp64, 0 },
-
-  { 0, 0, "la.pcrel", "r,la",
-    "pcaddu12i %1,%%pcrel(%2+0x800)>>12;"
-    "addi.d %1,%1,%%pcrel(%2+4)-(%%pcrel(%2+4+0x800)>>12<<12);",
-    &LARCH_opts.ase_lp64, 0, 0 },
-  { 0, 0, "la.pcrel", "r,r,la",
-    "pcaddu12i %1,(%%pcrel(%3)-(%%pcrel(%3+0x80000000)>>32<<32))<<32>>44;"
-    "ori %2,$r0,(%%pcrel(%3+4)-(%%pcrel(%3+4+0x80000000)>>32<<32))&0xfff;"
-    "lu32i.d %2,%%pcrel(%3+8+0x80000000)<<12>>44;"
-    "lu52i.d %2,%2,%%pcrel(%3+12+0x80000000)>>52;"
-    "add.d %1,%1,%2;",
-    &LARCH_opts.ase_lp64, 0, 0 },
-
-  { 0, 0, "la.got", "r,l",
-    "pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%gprel(%2))<<32>>44;"
-    "ld.w "
-    "%1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%gprel(%2)-((%%pcrel(_GLOBAL_"
-    "OFFSET_TABLE_+4+0x800)+%%gprel(%2))>>12<<12);",
-    &LARCH_opts.ase_ilp32, &LARCH_opts.ase_lp64, 0 },
-
-  { 0, 0, "la.got", "r,l",
-    "pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%gprel(%2))>>12;"
-    "ld.d "
-    "%1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%gprel(%2)-((%%pcrel(_GLOBAL_"
-    "OFFSET_TABLE_+4+0x800)+%%gprel(%2))>>12<<12);",
-    &LARCH_opts.ase_lp64, 0, 0 },
-  { 0, 0, "la.got", "r,r,l",
-    "pcaddu12i "
-    "%1,(%%pcrel(_GLOBAL_OFFSET_TABLE_)+%%gprel(%3)-((%%pcrel(_GLOBAL_OFFSET_"
-    "TABLE_+0x80000000)+%%gprel(%3))>>32<<32))<<32>>44;"
-    "ori "
-    "%2,$r0,(%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%gprel(%3)-((%%pcrel(_GLOBAL_"
-    "OFFSET_TABLE_+4+0x80000000)+%%gprel(%3))>>32<<32))&0xfff;"
-    "lu32i.d "
-    "%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+8+0x80000000)+%%gprel(%3))<<12>>44;"
-    "lu52i.d "
-    "%2,%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+12+0x80000000)+%%gprel(%3))>>52;"
-    "ldx.d %1,%1,%2;",
-    &LARCH_opts.ase_lp64, 0, 0 },
-
-  { 0, 0, "la.tls.le", "r,la",
-    "lu12i.w %1,%%tprel(%2)>>12;"
-    "ori %1,%1,%%tprel(%2)&0xfff",
-    &LARCH_opts.ase_ilp32, &LARCH_opts.ase_lp64, 0 },
-  /* { 0, 0, "la.tls.le", "r,la",
-  * "lu12i.w %1,%%tprel(%2)>>12;"
-  * "ori %1,%1,%%tprel(%2)&0xfff"
-  * , &LARCH_opts.addrwidth_is_64, 0, 0}, */
-  { 0, 0, "la.tls.le", "r,la",
-    "lu12i.w %1,%%tprel(%2)<<32>>44;"
-    "ori %1,%1,%%tprel(%2)&0xfff;"
-    "lu32i.d %1,%%tprel(%2)<<12>>44;"
-    "lu52i.d %1,%1,%%tprel(%2)>>52;",
-    &LARCH_opts.ase_lp64, 0, 0 },
-
-  { 0, 0, "la.tls.ie", "r,l",
-    "pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgot(%2))<<32>>44;"
-    "ld.w "
-    "%1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgot(%2)-((%%pcrel(_GLOBAL_"
-    "OFFSET_TABLE_+4+0x800)+%%tlsgot(%2))>>12<<12);",
-    &LARCH_opts.ase_ilp32, &LARCH_opts.ase_lp64, 0 },
-
-  { 0, 0, "la.tls.ie", "r,l",
-    "pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgot(%2))>>12;"
-    "ld.d "
-    "%1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgot(%2)-((%%pcrel(_GLOBAL_"
-    "OFFSET_TABLE_+4+0x800)+%%tlsgot(%2))>>12<<12);",
-    &LARCH_opts.ase_lp64, 0, 0 },
-  { 0, 0, "la.tls.ie", "r,r,l",
-    "pcaddu12i "
-    "%1,(%%pcrel(_GLOBAL_OFFSET_TABLE_)+%%tlsgot(%3)-((%%pcrel(_GLOBAL_OFFSET_"
-    "TABLE_+0x80000000)+%%tlsgot(%3))>>32<<32))<<32>>44;"
-    "ori "
-    "%2,$r0,(%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgot(%3)-((%%pcrel(_GLOBAL_"
-    "OFFSET_TABLE_+4+0x80000000)+%%tlsgot(%3))>>32<<32))&0xfff;"
-    "lu32i.d "
-    "%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+8+0x80000000)+%%tlsgot(%3))<<12>>44;"
-    "lu52i.d "
-    "%2,%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+12+0x80000000)+%%tlsgot(%3))>>52;"
-    "ldx.d %1,%1,%2;",
-    &LARCH_opts.ase_lp64, 0, 0 },
-
-  { 0, 0, "la.tls.ld", "r,l", "la.tls.gd %1,%2", 0, 0, 0 },
-  { 0, 0, "la.tls.ld", "r,r,l", "la.tls.gd %1,%2,%3",
-    &LARCH_opts.ase_lp64, 0, 0 },
-
-  { 0, 0, "la.tls.gd", "r,l",
-    "pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgd(%2))<<32>>44;"
-    "addi.w "
-    "%1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgd(%2)-((%%pcrel(_GLOBAL_"
-    "OFFSET_TABLE_+4+0x800)+%%tlsgd(%2))>>12<<12);",
-    &LARCH_opts.ase_ilp32, &LARCH_opts.ase_lp64, 0 },
-
-  { 0, 0, "la.tls.gd", "r,l",
-    "pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgd(%2))>>12;"
-    "addi.d "
-    "%1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgd(%2)-((%%pcrel(_GLOBAL_"
-    "OFFSET_TABLE_+4+0x800)+%%tlsgd(%2))>>12<<12);",
-    &LARCH_opts.ase_lp64, 0, 0 },
-  { 0, 0, "la.tls.gd", "r,r,l",
-    "pcaddu12i "
-    "%1,(%%pcrel(_GLOBAL_OFFSET_TABLE_)+%%tlsgd(%3)-((%%pcrel(_GLOBAL_OFFSET_"
-    "TABLE_+0x80000000)+%%tlsgd(%3))>>32<<32))<<32>>44;"
-    "ori "
-    "%2,$r0,(%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgd(%3)-((%%pcrel(_GLOBAL_"
-    "OFFSET_TABLE_+4+0x80000000)+%%tlsgd(%3))>>32<<32))&0xfff;"
-    "lu32i.d "
-    "%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+8+0x80000000)+%%tlsgd(%3))<<12>>44;"
-    "lu52i.d "
-    "%2,%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+12+0x80000000)+%%tlsgd(%3))>>52;"
-    "add.d %1,%1,%2;",
-    &LARCH_opts.ase_lp64, 0, 0 },
+  /* match,    mask,	   name, format, macro, include, exclude, pinfo.  */
+  { 0, 0, "li.w", "r,sc", "%f",	0, 0, 0 },
+  { 0, 0, "li.d", "r,sc", "%f",	0, 0, 0 },
+
+  { 0, 0, "la",		"r,la",	  "la.global %1,%2",	0,			0, 0 },
+  { 0, 0, "la.global",	"r,la",	  "la.pcrel %1,%2",	&LARCH_opts.ase_gpcr,	0, 0 },
+  { 0, 0, "la.global",	"r,r,la", "la.pcrel %1,%2,%3",	&LARCH_opts.ase_gpcr,	0, 0 },
+  { 0, 0, "la.global",	"r,la",	  "la.abs %1,%2",	&LARCH_opts.ase_gabs,	0, 0 },
+  { 0, 0, "la.global",	"r,r,la", "la.abs %1,%3",	&LARCH_opts.ase_gabs,	0, 0 },
+  { 0, 0, "la.global",	"r,la",	  "la.got %1,%2",	0,			0, 0 },
+  { 0, 0, "la.global",	"r,r,la", "la.got %1,%2,%3",	&LARCH_opts.ase_lp64,	0, 0 },
+
+  { 0, 0, "la.local",	"r,la",	  "la.abs %1,%2",	&LARCH_opts.ase_labs,	0, 0 },
+  { 0, 0, "la.local",	"r,r,la", "la.abs %1,%3",	&LARCH_opts.ase_labs,	0, 0 },
+  { 0, 0, "la.local",	"r,la",	  "la.pcrel %1,%2",	0,			0, 0 },
+  { 0, 0, "la.local",	"r,r,la", "la.pcrel %1,%2,%3",	&LARCH_opts.ase_lp64,	0, 0 },
+
+  { 0, 0, "la.abs",	"r,la",	  INSN_LA_ABS32,		0 },
+  { 0, 0, "la.abs",	"r,la",	  INSN_LA_ABS64,		0 },
+  { 0, 0, "la.pcrel",	"r,la",	  INSN_LA_PCREL32,		0 },
+  { 0, 0, "la.pcrel",	"r,la",	  INSN_LA_PCREL64,		0 },
+  { 0, 0, "la.pcrel",	"r,r,la", INSN_LA_PCREL64_LARGE,	0 },
+  { 0, 0, "la.got",	"r,la",	  INSN_LA_GOT32,		0 },
+  { 0, 0, "la.got",	"r,la",	  INSN_LA_GOT64,		0 },
+  { 0, 0, "la.got",	"r,la",	  INSN_LA_GOT64_LARGE_ABS,	0 },
+  { 0, 0, "la.got",	"r,r,la", INSN_LA_GOT64_LARGE_PCREL,	0 },
+  { 0, 0, "la.tls.le",	"r,l",	  INSN_LA_TLS_LE,		0 },
+  { 0, 0, "la.tls.le",	"r,l",	  INSN_LA_TLS_LE64_LARGE,	0 },
+  { 0, 0, "la.tls.ie",	"r,l",	  INSN_LA_TLS_IE32,		0 },
+  { 0, 0, "la.tls.ie",	"r,l",	  INSN_LA_TLS_IE64,		0 },
+  { 0, 0, "la.tls.ie",	"r,l",	  INSN_LA_TLS_IE64_LARGE_ABS,	0 },
+  { 0, 0, "la.tls.ie",	"r,r,l",  INSN_LA_TLS_IE64_LARGE_PCREL,	0 },
+  { 0, 0, "la.tls.ld",	"r,l",	  INSN_LA_TLS_LD32,		0 },
+  { 0, 0, "la.tls.ld",	"r,l",	  INSN_LA_TLS_LD64,		0 },
+  { 0, 0, "la.tls.ld",	"r,l",	  INSN_LA_TLS_LD64_LARGE_ABS,	0 },
+  { 0, 0, "la.tls.ld",	"r,r,l",  INSN_LA_TLS_LD64_LARGE_PCREL,	0 },
+  { 0, 0, "la.tls.gd",	"r,l",	  INSN_LA_TLS_GD32,		0 },
+  { 0, 0, "la.tls.gd",	"r,l",	  INSN_LA_TLS_GD64,		0 },
+  { 0, 0, "la.tls.gd",	"r,l",	  INSN_LA_TLS_GD64_LARGE_ABS,	0 },
+  { 0, 0, "la.tls.gd",	"r,r,l",  INSN_LA_TLS_GD64_LARGE_PCREL,	0 },
 
   { 0 } /* Terminate the list.  */
 };
@@ -728,9 +775,9 @@ static struct loongarch_opcode loongarch_double_float_load_store_opcodes[] =
 
 static struct loongarch_opcode loongarch_float_jmp_opcodes[] =
 {
-  { 0x0,	0x0,		"bceqz",	"c,la",				"bceqz %1,%%pcrel(%2)",		0, 0, 0 },
+  { 0x0,	0x0,		"bceqz",	"c,la",				"bceqz %1,%%b21(%2)",		0, 0, 0 },
   { 0x48000000, 0xfc000300,	"bceqz",	"c5:3,sb0:5|10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"bcnez",	"c,la",				"bcnez %1,%%pcrel(%2)",		0, 0, 0 },
+  { 0x0,	0x0,		"bcnez",	"c,la",				"bcnez %1,%%b21(%2)",		0, 0, 0 },
   { 0x48000100, 0xfc000300,	"bcnez",	"c5:3,sb0:5|10:16<<2",		0,				0, 0, 0 },
   { 0 } /* Terminate the list.  */
 };
@@ -738,43 +785,43 @@ static struct loongarch_opcode loongarch_float_jmp_opcodes[] =
 static struct loongarch_opcode loongarch_jmp_opcodes[] =
 {
   /* match,	mask,		name,		format,				macro,			include, exclude, pinfo.  */
-  { 0x0,	0x0,		"bltz",		"r,la",				"bltz %1,%%pcrel(%2)",		0, 0, 0 },
+  { 0x0,	0x0,		"bltz",		"r,la",				"bltz %1,%%b16(%2)",		0, 0, 0 },
   { 0x60000000, 0xfc00001f,	"bltz",		"r5:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"bgtz",		"r,la",				"bgtz %1,%%pcrel(%2)",		0, 0, 0 },
+  { 0x0,	0x0,		"bgtz",		"r,la",				"bgtz %1,%%b16(%2)",		0, 0, 0 },
   { 0x60000000, 0xfc0003e0,	"bgtz",		"r0:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"bgez",		"r,la",				"bgez %1,%%pcrel(%2)",		0, 0, 0 },
+  { 0x0,	0x0,		"bgez",		"r,la",				"bgez %1,%%b16(%2)",		0, 0, 0 },
   { 0x64000000, 0xfc00001f,	"bgez",		"r5:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"blez",		"r,la",				"blez %1,%%pcrel(%2)",		0, 0, 0 },
+  { 0x0,	0x0,		"blez",		"r,la",				"blez %1,%%b16(%2)",		0, 0, 0 },
   { 0x64000000, 0xfc0003e0,	"blez",		"r0:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"beqz",		"r,la",				"beqz %1,%%pcrel(%2)",		0, 0, 0 },
+  { 0x0,	0x0,		"beqz",		"r,la",				"beqz %1,%%b21(%2)",		0, 0, 0 },
   { 0x40000000, 0xfc000000,	"beqz",		"r5:5,sb0:5|10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"bnez",		"r,la",				"bnez %1,%%pcrel(%2)",		0, 0, 0 },
+  { 0x0,	0x0,		"bnez",		"r,la",				"bnez %1,%%b21(%2)",		0, 0, 0 },
   { 0x44000000, 0xfc000000,	"bnez",		"r5:5,sb0:5|10:16<<2",		0,				0, 0, 0 },
   { 0x0,	0x0,		"jr",		"r",				"jirl $r0,%1,0",		0, 0, 0 },
   { 0x50000000, 0xfc000000,	"b",		"sb0:10|10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"b",		"la",				"b %%pcrel(%1)",		0, 0, 0 },
+  { 0x0,	0x0,		"b",		"la",				"b %%b26(%1)",			0, 0, 0 },
   { 0x4c000000, 0xfc000000,	"jirl",		"r0:5,r5:5,s10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"bl",		"la",				"bl %%pcrel(%1)",		0, 0, 0 },
+  { 0x0,	0x0,		"bl",		"la",				"bl %%b26(%1)",			0, 0, 0 },
   { 0x54000000, 0xfc000000,	"bl",		"sb0:10|10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"beq",		"r,r,la",			"beq %1,%2,%%pcrel(%3)",	0, 0, 0 },
+  { 0x0,	0x0,		"beq",		"r,r,la",			"beq %1,%2,%%b16(%3)",		0, 0, 0 },
   { 0x58000000, 0xfc000000,	"beq",		"r5:5,r0:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"bne",		"r,r,la",			"bne %1,%2,%%pcrel(%3)",	0, 0, 0 },
+  { 0x0,	0x0,		"bne",		"r,r,la",			"bne %1,%2,%%b16(%3)",		0, 0, 0 },
   { 0x5c000000, 0xfc000000,	"bne",		"r5:5,r0:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"blt",		"r,r,la",			"blt %1,%2,%%pcrel(%3)",	0, 0, 0 },
+  { 0x0,	0x0,		"blt",		"r,r,la",			"blt %1,%2,%%b16(%3)",		0, 0, 0 },
   { 0x60000000, 0xfc000000,	"blt",		"r5:5,r0:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"bgt",		"r,r,la",			"bgt %1,%2,%%pcrel(%3)",	0, 0, 0 },
+  { 0x0,	0x0,		"bgt",		"r,r,la",			"bgt %1,%2,%%b16(%3)",		0, 0, 0 },
   { 0x60000000, 0xfc000000,	"bgt",		"r0:5,r5:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"bge",		"r,r,la",			"bge %1,%2,%%pcrel(%3)",	0, 0, 0 },
+  { 0x0,	0x0,		"bge",		"r,r,la",			"bge %1,%2,%%b16(%3)",		0, 0, 0 },
   { 0x64000000, 0xfc000000,	"bge",		"r5:5,r0:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"ble",		"r,r,la",			"ble %1,%2,%%pcrel(%3)",	0, 0, 0 },
+  { 0x0,	0x0,		"ble",		"r,r,la",			"ble %1,%2,%%b16(%3)",		0, 0, 0 },
   { 0x64000000, 0xfc000000,	"ble",		"r0:5,r5:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"bltu",		"r,r,la",			"bltu %1,%2,%%pcrel(%3)",	0, 0, 0 },
+  { 0x0,	0x0,		"bltu",		"r,r,la",			"bltu %1,%2,%%b16(%3)",		0, 0, 0 },
   { 0x68000000, 0xfc000000,	"bltu",		"r5:5,r0:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"bgtu",		"r,r,la",			"bgtu %1,%2,%%pcrel(%3)",	0, 0, 0 },
+  { 0x0,	0x0,		"bgtu",		"r,r,la",			"bgtu %1,%2,%%b16(%3)",		0, 0, 0 },
   { 0x68000000, 0xfc000000,	"bgtu",		"r0:5,r5:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"bgeu",		"r,r,la",			"bgeu %1,%2,%%pcrel(%3)",	0, 0, 0 },
+  { 0x0,	0x0,		"bgeu",		"r,r,la",			"bgeu %1,%2,%%b16(%3)",		0, 0, 0 },
   { 0x6c000000, 0xfc000000,	"bgeu",		"r5:5,r0:5,sb10:16<<2",		0,				0, 0, 0 },
-  { 0x0,	0x0,		"bleu",		"r,r,la",			"bleu %1,%2,%%pcrel(%3)",	0, 0, 0 },
+  { 0x0,	0x0,		"bleu",		"r,r,la",			"bleu %1,%2,%%b16(%3)",		0, 0, 0 },
   { 0x6c000000, 0xfc000000,	"bleu",		"r0:5,r5:5,sb10:16<<2",		0,				0, 0, 0 },
   { 0 } /* Terminate the list.  */
 };
-- 
2.31.1


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 3/5 v1] LoongArch: gas: Add new reloc types.
  2022-07-18  8:43 [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types liuzhensong
  2022-07-18  8:43 ` [PATCH 2/5 v1] LoongArch:opcodes: " liuzhensong
@ 2022-07-18  8:43 ` liuzhensong
  2022-07-18  8:43 ` [PATCH 4/5 v1] LoongArch: Move ifunc info to rela.dyn from rela.plt liuzhensong
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 24+ messages in thread
From: liuzhensong @ 2022-07-18  8:43 UTC (permalink / raw)
  To: binutils; +Cc: xuchenghua, mengqinggang, liuzhensong

  Generate new relocate types while use new macro insns.

  gas/config/
    loongarch-lex.h
    loongarch-parse.y
    tc-loongarch.c
    tc-loongarch.h
---
 gas/config/loongarch-lex.h   |   3 +
 gas/config/loongarch-parse.y |  72 +++++-------------
 gas/config/tc-loongarch.c    | 140 ++++++++++++++++++++++++-----------
 gas/config/tc-loongarch.h    |   7 +-
 4 files changed, 120 insertions(+), 102 deletions(-)

diff --git a/gas/config/loongarch-lex.h b/gas/config/loongarch-lex.h
index 59212442242..35d22dbdbc9 100644
--- a/gas/config/loongarch-lex.h
+++ b/gas/config/loongarch-lex.h
@@ -32,3 +32,6 @@ loongarch_parse_expr (const char *expr,
 		      size_t max_reloc_num,
 		      size_t *reloc_num,
 		      offsetT *imm);
+bfd_reloc_code_real_type
+loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+				   const char *l_r_name);
diff --git a/gas/config/loongarch-parse.y b/gas/config/loongarch-parse.y
index 710f854c74f..902d7204e8e 100644
--- a/gas/config/loongarch-parse.y
+++ b/gas/config/loongarch-parse.y
@@ -83,11 +83,11 @@ static const char *
 my_getExpression (expressionS *ep, const char *str)
 {
   char *save_in, *ret;
+
   if (*str == ':')
     {
       unsigned long j;
       char *str_1 = (char *) str;
-      str_1++;
       j = strtol (str_1, &str_1, 10);
       get_internal_label (ep, j, *str_1 == 'f');
       return NULL;
@@ -104,65 +104,31 @@ static void
 reloc (const char *op_c_str, const char *id_c_str, offsetT addend)
 {
   expressionS id_sym_expr;
+  bfd_reloc_code_real_type btype;
 
   if (end <= top)
     as_fatal (_("expr too huge"));
 
-  if (id_c_str)
-    {
-      my_getExpression (&id_sym_expr, id_c_str);
-      id_sym_expr.X_add_number += addend;
-    }
+  /* For compatible old asm code.  */
+  if (0 == strcmp (op_c_str, "plt"))
+    btype = BFD_RELOC_LARCH_B26;
   else
-    {
-      id_sym_expr.X_op = O_constant;
-      id_sym_expr.X_add_number = addend;
-    }
+    btype = loongarch_larch_reloc_name_lookup (NULL, op_c_str);
 
-  if (strcmp (op_c_str, "abs") == 0)
-    {
-      top->value = id_sym_expr;
-      top->type = BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE;
-      top++;
-    }
-  else if (strcmp (op_c_str, "pcrel") == 0)
-    {
-      top->value = id_sym_expr;
-      top->type = BFD_RELOC_LARCH_SOP_PUSH_PCREL;
-      top++;
-    }
-  else if (strcmp (op_c_str, "gprel") == 0)
-    {
-      top->value = id_sym_expr;
-      top->type = BFD_RELOC_LARCH_SOP_PUSH_GPREL;
-      top++;
-    }
-  else if (strcmp (op_c_str, "tprel") == 0)
-    {
-      top->value = id_sym_expr;
-      top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL;
-      top++;
-    }
-  else if (strcmp (op_c_str, "tlsgot") == 0)
-    {
-      top->value = id_sym_expr;
-      top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT;
-      top++;
-    }
-  else if (strcmp (op_c_str, "tlsgd") == 0)
-    {
-      top->value = id_sym_expr;
-      top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_GD;
-      top++;
-    }
-  else if (strcmp (op_c_str, "plt") == 0)
-    {
-      top->value = id_sym_expr;
-      top->type = BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL;
-      top++;
-    }
+  if (id_c_str)
+  {
+    my_getExpression (&id_sym_expr, id_c_str);
+    id_sym_expr.X_add_number += addend;
+  }
   else
-    as_fatal (_("unknown reloc hint: %s"), op_c_str);
+  {
+    id_sym_expr.X_op = O_constant;
+    id_sym_expr.X_add_number = addend;
+  }
+
+  top->value = id_sym_expr;
+  top->type = btype;
+  top++;
 }
 
 static void
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index 08203d291bd..e9c1a536505 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -362,18 +362,6 @@ loongarch_mach (void)
 
 static const expressionS const_0 = { .X_op = O_constant, .X_add_number = 0 };
 
-static const char *
-my_getExpression (expressionS *ep, const char *str)
-{
-  char *save_in, *ret;
-  save_in = input_line_pointer;
-  input_line_pointer = (char *) str;
-  expression (ep);
-  ret = input_line_pointer;
-  input_line_pointer = save_in;
-  return ret;
-}
-
 static void
 s_loongarch_align (int arg)
 {
@@ -480,11 +468,6 @@ get_internal_label (expressionS *label_expr, unsigned long label,
   label_expr->X_add_number = 0;
 }
 
-extern int loongarch_parse_expr (const char *expr,
-				 struct reloc_info *reloc_stack_top,
-				 size_t max_reloc_num, size_t *reloc_num,
-				 offsetT *imm_if_no_reloc);
-
 static int
 is_internal_label (const char *c_str)
 {
@@ -652,6 +635,15 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
 	    as_fatal (
 		      _("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"),
 		      esc_ch1, esc_ch2, bit_field, arg);
+	  if (ip->reloc_info[0].type >= BFD_RELOC_LARCH_B16
+	      && ip->reloc_info[0].type < BFD_RELOC_LARCH_RELAX)
+	    {
+	      /* As we compact stack-relocs, it is no need for pop operation.
+		 But break out until here in order to check the imm field.
+		 May be reloc_num > 1 if implement relax?  */
+	      ip->reloc_num += reloc_num;
+	      break;
+	    }
 	  reloc_num++;
 	  ip->reloc_num += reloc_num;
 	  ip->reloc_info[ip->reloc_num - 1].type = reloc_type;
@@ -767,7 +759,12 @@ get_loongarch_opcode (struct loongarch_cl_insn *insn)
 	{
 	  ase->name_hash_entry = str_htab_create ();
 	  for (it = ase->opcodes; it->name; it++)
-	    str_hash_insert (ase->name_hash_entry, it->name, (void *) it, 0);
+	    {
+	      if ((!it->include || (it->include && *it->include))
+		  && (!it->exclude || (it->exclude && !(*it->exclude))))
+		str_hash_insert (ase->name_hash_entry, it->name,
+				 (void *) it, 0);
+	    }
 	}
 
       if ((it = str_hash_find (ase->name_hash_entry, insn->name)) == NULL)
@@ -800,10 +797,11 @@ static int
 check_this_insn_before_appending (struct loongarch_cl_insn *ip)
 {
   int ret = 0;
-  if (strcmp (ip->name, "la.abs") == 0)
+
+  if (strncmp (ip->name, "la.abs", 6) == 0)
     {
       ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_MARK_LA;
-      my_getExpression (&ip->reloc_info[ip->reloc_num].value, ip->arg_strs[1]);
+      ip->reloc_info[ip->reloc_num].value = const_0;
       ip->reloc_num++;
     }
   else if (ip->insn->mask == 0xffff8000
@@ -980,6 +978,7 @@ assember_macro_helper (const char *const args[], void *context_ptr)
       ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL,
 				    sizeof (args_buf));
     }
+
   return ret;
 }
 
@@ -1096,6 +1095,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
   static int64_t stack_top;
   static int last_reloc_is_sop_push_pcrel_1 = 0;
   int last_reloc_is_sop_push_pcrel = last_reloc_is_sop_push_pcrel_1;
+  segT sub_segment;
   last_reloc_is_sop_push_pcrel_1 = 0;
 
   char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
@@ -1104,26 +1104,40 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL:
     case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD:
     case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT:
-    case BFD_RELOC_LARCH_SOP_PUSH_PCREL:
-    case BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL:
+    case BFD_RELOC_LARCH_TLS_LE_HI20:
+    case BFD_RELOC_LARCH_TLS_LE_LO12:
+    case BFD_RELOC_LARCH_TLS_LE64_LO20:
+    case BFD_RELOC_LARCH_TLS_LE64_HI12:
+    case BFD_RELOC_LARCH_TLS_IE_PC_HI20:
+    case BFD_RELOC_LARCH_TLS_IE_PC_LO12:
+    case BFD_RELOC_LARCH_TLS_IE64_PC_LO20:
+    case BFD_RELOC_LARCH_TLS_IE64_PC_HI12:
+    case BFD_RELOC_LARCH_TLS_IE64_HI20:
+    case BFD_RELOC_LARCH_TLS_IE64_LO12:
+    case BFD_RELOC_LARCH_TLS_IE64_LO20:
+    case BFD_RELOC_LARCH_TLS_IE64_HI12:
+    case BFD_RELOC_LARCH_TLS_LD_PC_HI20:
+    case BFD_RELOC_LARCH_TLS_LD64_HI20:
+    case BFD_RELOC_LARCH_TLS_GD_PC_HI20:
+    case BFD_RELOC_LARCH_TLS_GD64_HI20:
+      /* Add tls lo (got_lo reloc type).  */
       if (fixP->fx_addsy == NULL)
 	as_bad_where (fixP->fx_file, fixP->fx_line,
 		      _("Relocation against a constant"));
+      S_SET_THREAD_LOCAL (fixP->fx_addsy);
+      break;
 
-      if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL
-	  || fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_GD
-	  || fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT)
-	S_SET_THREAD_LOCAL (fixP->fx_addsy);
+    case BFD_RELOC_LARCH_SOP_PUSH_PCREL:
+      if (fixP->fx_addsy == NULL)
+	as_bad_where (fixP->fx_file, fixP->fx_line,
+		      _("Relocation against a constant"));
 
-      if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_PCREL)
-	{
-	  last_reloc_is_sop_push_pcrel_1 = 1;
-	  if (S_GET_SEGMENT (fixP->fx_addsy) == seg)
-	    stack_top = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
-			 - (fixP->fx_where + fixP->fx_frag->fr_address));
-	  else
-	    stack_top = 0;
-	}
+      last_reloc_is_sop_push_pcrel_1 = 1;
+      if (S_GET_SEGMENT (fixP->fx_addsy) == seg)
+	stack_top = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
+		     - (fixP->fx_where + fixP->fx_frag->fr_address));
+      else
+	stack_top = 0;
       break;
 
     case BFD_RELOC_LARCH_SOP_POP_32_S_10_5:
@@ -1143,11 +1157,24 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 
     case BFD_RELOC_64:
     case BFD_RELOC_32:
+    case BFD_RELOC_24:
+    case BFD_RELOC_16:
+    case BFD_RELOC_8:
+
+      if (fixP->fx_r_type == BFD_RELOC_32
+	  && fixP->fx_addsy && fixP->fx_subsy
+	  && (sub_segment = S_GET_SEGMENT (fixP->fx_subsy))
+	  && strcmp (sub_segment->name, ".eh_frame") == 0
+	  && S_GET_VALUE (fixP->fx_subsy)
+	  == fixP->fx_frag->fr_address + fixP->fx_where)
+	{
+	  fixP->fx_r_type = BFD_RELOC_LARCH_32_PCREL;
+	  fixP->fx_subsy = NULL;
+	  break;
+	}
+
       if (fixP->fx_subsy)
 	{
-	case BFD_RELOC_24:
-	case BFD_RELOC_16:
-	case BFD_RELOC_8:
 	  fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
 	  fixP->fx_next->fx_addsy = fixP->fx_subsy;
 	  fixP->fx_next->fx_subsy = NULL;
@@ -1190,6 +1217,25 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 	}
       break;
 
+    case BFD_RELOC_LARCH_B16:
+    case BFD_RELOC_LARCH_B21:
+    case BFD_RELOC_LARCH_B26:
+      if (fixP->fx_addsy == NULL)
+	{
+	  as_bad_where (fixP->fx_file, fixP->fx_line,
+			_ ("Relocation against a constant."));
+	}
+      if (S_GET_SEGMENT (fixP->fx_addsy) == seg
+	  && !S_FORCE_RELOC (fixP->fx_addsy, 1))
+	{
+	  int64_t sym_addend = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset;
+	  int64_t pc = fixP->fx_where + fixP->fx_frag->fr_address;
+	  fix_reloc_insn (fixP, sym_addend - pc, buf);
+	  fixP->fx_done = 1;
+	}
+
+      break;
+
     default:
       break;
     }
@@ -1210,6 +1256,18 @@ md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
   return 0;
 }
 
+int
+loongarch_fix_adjustable (fixS *fix)
+{
+  /* Prevent all adjustments to global symbols.  */
+  if (S_IS_EXTERNAL (fix->fx_addsy)
+      || S_IS_WEAK (fix->fx_addsy)
+      || S_FORCE_RELOC (fix->fx_addsy, true))
+    return 0;
+
+  return 1;
+}
+
 /* Translate internal representation of relocation info to BFD target
    format.  */
 arelent *
@@ -1249,12 +1307,6 @@ loongarch_cfi_frame_initial_instructions (void)
   cfi_add_CFA_def_cfa_register (3 /* $sp */);
 }
 
-int
-loongarch_dwarf2_addr_size (void)
-{
-  return LARCH_opts.ase_lp64 ? 8 : 4;
-}
-
 void
 tc_loongarch_parse_to_dw2regnum (expressionS *exp)
 {
diff --git a/gas/config/tc-loongarch.h b/gas/config/tc-loongarch.h
index 2664da59f51..f05926d7d67 100644
--- a/gas/config/tc-loongarch.h
+++ b/gas/config/tc-loongarch.h
@@ -49,7 +49,8 @@ extern int loongarch_relax_frag (asection *, struct frag *, long);
 
 /* This is called to see whether a reloc against a defined symbol
    should be converted into a reloc against a section.  */
-#define tc_fix_adjustable(fixp) 0
+extern int loongarch_fix_adjustable (struct fix *fix);
+#define tc_fix_adjustable(fixp) loongarch_fix_adjustable(fixp)
 
 /* Values passed to md_apply_fix don't include symbol values.  */
 #define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) 1
@@ -59,10 +60,6 @@ extern int loongarch_relax_frag (asection *, struct frag *, long);
 #define TARGET_USE_CFIPOP 1
 #define DWARF2_DEFAULT_RETURN_COLUMN 1 /* $ra.  */
 #define DWARF2_CIE_DATA_ALIGNMENT -4
-extern int loongarch_dwarf2_addr_size (void);
-#define DWARF2_FDE_RELOC_SIZE loongarch_dwarf2_addr_size ()
-#define DWARF2_ADDR_SIZE(bfd) loongarch_dwarf2_addr_size ()
-#define CFI_DIFF_EXPR_OK 0
 
 #define tc_cfi_frame_initial_instructions	\
   loongarch_cfi_frame_initial_instructions
-- 
2.31.1


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 4/5 v1] LoongArch: Move ifunc info to rela.dyn from rela.plt.
  2022-07-18  8:43 [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types liuzhensong
  2022-07-18  8:43 ` [PATCH 2/5 v1] LoongArch:opcodes: " liuzhensong
  2022-07-18  8:43 ` [PATCH 3/5 v1] LoongArch: gas: " liuzhensong
@ 2022-07-18  8:43 ` liuzhensong
  2022-07-18 11:45   ` Xi Ruoyao
  2022-07-18 16:27   ` Xi Ruoyao
  2022-07-18  8:43 ` [PATCH 5/5 v1] LoongArch: Delete R_LARCH_NONE from dynamic info liuzhensong
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 24+ messages in thread
From: liuzhensong @ 2022-07-18  8:43 UTC (permalink / raw)
  To: binutils; +Cc: xuchenghua, mengqinggang, liuzhensong

  Delete R_LARCH_IRELATIVE from dynamic loader (glibc ld.so) when
  loading lazy function (rela.plt section).

  In dynamic programes, move ifunc dynamic relocate info to section
  srelgot from srelplt.

  bfd/
    elfnn-loongarch.c
---
 bfd/elfnn-loongarch.c | 322 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 310 insertions(+), 12 deletions(-)

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 4eeaeb44eff..5bb7596e5d0 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -1207,6 +1207,259 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   return true;
 }
 
+/* Based function _bfd_elf_allocate_ifunc_dyn_relocs.
+   For local def and ref ifunc,
+   dynamic relocations are stored in
+   1.  rel[a].irelifunc section in PIC object.
+   2.  rel[a].srelgot section in dynamic executable.
+   3.  rel[a].irelplt section in static executable.
+   Change ifunc dynamic info from srelplt to srelgot.
+   In loader, remove R_LARCH_IRELACTIVE from rela lazy in ld.so.  */
+
+static bool
+local_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
+				    struct elf_link_hash_entry *h,
+				    struct elf_dyn_relocs **head,
+				    unsigned int plt_entry_size,
+				    unsigned int plt_header_size,
+				    unsigned int got_entry_size,
+				    bool avoid_plt)
+{
+  asection *plt, *gotplt, *relplt;
+  struct elf_dyn_relocs *p;
+  unsigned int sizeof_reloc;
+  const struct elf_backend_data *bed;
+  struct elf_link_hash_table *htab;
+  /* If AVOID_PLT is TRUE, don't use PLT if possible.  */
+  bool use_plt = !avoid_plt || h->plt.refcount > 0;
+  bool need_dynreloc = !use_plt || bfd_link_pic (info);
+
+  /* When a PIC object references a STT_GNU_IFUNC symbol defined
+     in executable or it isn't referenced via PLT, the address of
+     the resolved function may be used.  But in non-PIC executable,
+     the address of its plt slot may be used.  Pointer equality may
+     not work correctly.  PIE or non-PLT reference should be used if
+     pointer equality is required here.
+
+     If STT_GNU_IFUNC symbol is defined in position-dependent executable,
+     backend should change it to the normal function and set its address
+     to its PLT entry which should be resolved by R_*_IRELATIVE at
+     run-time.  All external references should be resolved to its PLT in
+     executable.  */
+  if (!need_dynreloc
+      && !(bfd_link_pde (info) && h->def_regular)
+      && (h->dynindx != -1
+	  || info->export_dynamic)
+      && h->pointer_equality_needed)
+    {
+      info->callbacks->einfo
+	/* xgettext:c-format.  */
+	(_("%F%P: dynamic STT_GNU_IFUNC symbol `%s' with pointer "
+	   "equality in `%pB' can not be used when making an "
+	   "executable; recompile with -fPIE and relink with -pie\n"),
+	 h->root.root.string,
+	 h->root.u.def.section->owner);
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
+
+  htab = elf_hash_table (info);
+
+  /* When the symbol is marked with regular reference, if PLT isn't used
+     or we are building a PIC object, we must keep dynamic relocation
+     if there is non-GOT reference and use PLT if there is PC-relative
+     reference.  */
+  if (need_dynreloc && h->ref_regular)
+    {
+      bool keep = false;
+      for (p = *head; p != NULL; p = p->next)
+	if (p->count)
+	  {
+	    h->non_got_ref = 1;
+	    /* Need dynamic relocations for non-GOT reference.  */
+	    keep = true;
+	    if (p->pc_count)
+	      {
+		/* Must use PLT for PC-relative reference.  */
+		use_plt = true;
+		need_dynreloc = bfd_link_pic (info);
+		break;
+	      }
+	  }
+      if (keep)
+	goto keep;
+    }
+
+  /* Support garbage collection against STT_GNU_IFUNC symbols.  */
+  if (h->plt.refcount <= 0 && h->got.refcount <= 0)
+    {
+      h->got = htab->init_got_offset;
+      h->plt = htab->init_plt_offset;
+      *head = NULL;
+      return true;
+    }
+
+  /* Return and discard space for dynamic relocations against it if
+     it is never referenced.  */
+  if (!h->ref_regular)
+    {
+      if (h->plt.refcount > 0
+	  || h->got.refcount > 0)
+	abort ();
+      h->got = htab->init_got_offset;
+      h->plt = htab->init_plt_offset;
+      *head = NULL;
+      return true;
+    }
+
+ keep:
+  bed = get_elf_backend_data (info->output_bfd);
+  if (bed->rela_plts_and_copies_p)
+    sizeof_reloc = bed->s->sizeof_rela;
+  else
+    sizeof_reloc = bed->s->sizeof_rel;
+
+  /* When building a static executable, use iplt, igot.plt and
+     rel[a].iplt sections for STT_GNU_IFUNC symbols.  */
+  if (htab->splt != NULL)
+    {
+      plt = htab->splt;
+      gotplt = htab->sgotplt;
+      /* Change dynamic info of ifunc gotplt from srelplt to srelgot.  */
+      relplt = htab->srelgot;
+
+      /* If this is the first plt entry and PLT is used, make room for
+	 the special first entry.  */
+      if (plt->size == 0 && use_plt)
+	plt->size += plt_header_size;
+    }
+  else
+    {
+      plt = htab->iplt;
+      gotplt = htab->igotplt;
+      relplt = htab->irelplt;
+    }
+
+  if (use_plt)
+    {
+      /* Don't update value of STT_GNU_IFUNC symbol to PLT.  We need
+	 the original value for R_*_IRELATIVE.  */
+      h->plt.offset = plt->size;
+
+      /* Make room for this entry in the plt/iplt section.  */
+      plt->size += plt_entry_size;
+
+      /* We also need to make an entry in the got.plt/got.iplt section,
+	 which will be placed in the got section by the linker script.  */
+      gotplt->size += got_entry_size;
+    }
+
+  /* We also need to make an entry in the rel[a].plt/.rel[a].iplt
+     section for GOTPLT relocation if PLT is used.  */
+  if (use_plt)
+    {
+      relplt->size += sizeof_reloc;
+      relplt->reloc_count++;
+    }
+
+  /* We need dynamic relocation for STT_GNU_IFUNC symbol only when
+     there is a non-GOT reference in a PIC object or PLT isn't used.  */
+  if (!need_dynreloc || !h->non_got_ref)
+    *head = NULL;
+
+  /* Finally, allocate space.  */
+  p = *head;
+  if (p != NULL)
+    {
+      bfd_size_type count = 0;
+      do
+	{
+	  count += p->count;
+	  p = p->next;
+	}
+      while (p != NULL);
+
+      htab->ifunc_resolvers = count != 0;
+
+      /* Dynamic relocations are stored in
+	 1.  rel[a].srelgot section in PIC object.
+	 2.  rel[a].srelgot section in dynamic executable.
+	 3.  rel[a].irelplt section in static executable.  */
+      if (htab->splt != NULL)
+	htab->srelgot->size += count * sizeof_reloc;
+      else
+	{
+	  relplt->size += count * sizeof_reloc;
+	  relplt->reloc_count += count;
+	}
+    }
+
+  /* For STT_GNU_IFUNC symbol, got.plt has the real function address
+     and got has the PLT entry adddress.  We will load the GOT entry
+     with the PLT entry in finish_dynamic_symbol if it is used.  For
+     branch, it uses got.plt.  For symbol value, if PLT is used,
+     1.  Use got.plt in a PIC object if it is forced local or not
+     dynamic.
+     2.  Use got.plt in a non-PIC object if pointer equality isn't
+     needed.
+     3.  Use got.plt in PIE.
+     4.  Use got.plt if got isn't used.
+     5.  Otherwise use got so that it can be shared among different
+     objects at run-time.
+     If PLT isn't used, always use got for symbol value.
+     We only need to relocate got entry in PIC object or in dynamic
+     executable without PLT.  */
+  if (use_plt
+      && (h->got.refcount <= 0
+	  || (bfd_link_pic (info)
+	      && (h->dynindx == -1
+		  || h->forced_local))
+	  || (
+	      !h->pointer_equality_needed)
+	  || htab->sgot == NULL))
+    {
+      /* Use got.plt.  */
+      h->got.offset = (bfd_vma) -1;
+    }
+  else
+    {
+      if (!use_plt)
+	{
+	  /* PLT isn't used.  */
+	  h->plt.offset = (bfd_vma) -1;
+	}
+      if (h->got.refcount <= 0)
+	{
+	  /* GOT isn't need when there are only relocations for static
+	     pointers.  */
+	  h->got.offset = (bfd_vma) -1;
+	}
+      else
+	{
+	  h->got.offset = htab->sgot->size;
+	  htab->sgot->size += got_entry_size;
+	  /* Need to relocate the GOT entry in a PIC object or PLT isn't
+	     used.  Otherwise, the GOT entry will be filled with the PLT
+	     entry and dynamic GOT relocation isn't needed.  */
+	  if (need_dynreloc)
+	    {
+	      /* For non-static executable, dynamic GOT relocation is in
+		 rel[a].got section, but for static executable, it is
+		 in rel[a].iplt section.  */
+	      if (htab->splt != NULL)
+		htab->srelgot->size += sizeof_reloc;
+	      else
+		{
+		  relplt->size += sizeof_reloc;
+		  relplt->reloc_count++;
+		}
+	    }
+	}
+    }
+
+  return true;
+}
+
 /* Allocate space in .plt, .got and associated reloc sections for
    ifunc dynamic relocs.  */
 
@@ -1234,12 +1487,23 @@ elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
      here if it is defined and referenced in a non-shared object.  */
   if (h->type == STT_GNU_IFUNC && h->def_regular)
-    return _bfd_elf_allocate_ifunc_dyn_relocs (info, h,
+    {
+      if (SYMBOL_REFERENCES_LOCAL (info, h))
+	return local_allocate_ifunc_dyn_relocs (info, h,
 					       &h->dyn_relocs,
 					       PLT_ENTRY_SIZE,
 					       PLT_HEADER_SIZE,
 					       GOT_ENTRY_SIZE,
 					       false);
+      else
+	return _bfd_elf_allocate_ifunc_dyn_relocs (info, h,
+					       &h->dyn_relocs,
+					       PLT_ENTRY_SIZE,
+					       PLT_HEADER_SIZE,
+					       GOT_ENTRY_SIZE,
+					       false);
+
+    }
 
   return true;
 }
@@ -2175,7 +2439,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 				     + h->root.u.def.section->output_offset);
 
 		  if (htab->elf.splt != NULL)
-		    sreloc = htab->elf.srelplt;
+		    sreloc = htab->elf.srelgot;
 		  else
 		    sreloc = htab->elf.irelplt;
 		}
@@ -2818,10 +3082,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	case R_LARCH_PCALA64_LO20:
 	case R_LARCH_PCALA64_HI12:
 	  if (h && h->plt.offset != MINUS_ONE)
-	    {
-	      BFD_ASSERT (rel->r_addend == 0);
-	      relocation = sec_addr (plt) + h->plt.offset;
-	    }
+	    relocation = sec_addr (plt) + h->plt.offset;
 	  else
 	    relocation += rel->r_addend;
 
@@ -3239,7 +3500,10 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
 
 	  plt = htab->elf.splt;
 	  gotplt = htab->elf.sgotplt;
-	  relplt = htab->elf.srelplt;
+	  if (h->type == STT_GNU_IFUNC && SYMBOL_REFERENCES_LOCAL (info, h))
+	    relplt = htab->elf.srelgot;
+	  else
+	    relplt = htab->elf.srelplt;
 	  plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
 	  got_address =
 	    sec_addr (gotplt) + GOTPLT_HEADER_SIZE + plt_idx * GOT_ENTRY_SIZE;
@@ -3274,11 +3538,45 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
 
       rela.r_offset = got_address;
 
-      /* Fill in the entry in the rela.plt section.  */
-      rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT);
-      rela.r_addend = 0;
-      loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela);
-      bed->s->swap_reloca_out (output_bfd, &rela, loc);
+      /* TRUE if this is a PLT reference to a local IFUNC.  */
+      if (PLT_LOCAL_IFUNC_P (info, h)
+	  && (relplt == htab->elf.srelgot
+	      || relplt == htab->elf.irelplt))
+	{
+	    {
+	      rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
+	      rela.r_addend = (h->root.u.def.value
+			       + h->root.u.def.section->output_section->vma
+			       + h->root.u.def.section->output_offset);
+	    }
+
+	    /* Find the space after dyn sort.  */
+	    {
+	      Elf_Internal_Rela *dyn = (Elf_Internal_Rela *)relplt->contents;
+	      bool fill = false;
+	      for (;dyn < dyn + relplt->size / sizeof (*dyn); dyn++)
+		{
+		  if (0 == dyn->r_offset)
+		    {
+		      bed->s->swap_reloca_out (output_bfd, &rela,
+					       (bfd_byte *)dyn);
+		      relplt->reloc_count++;
+		      fill = true;
+		      break;
+		    }
+		}
+	      BFD_ASSERT (fill);
+	    }
+
+	}
+      else
+	{
+	  /* Fill in the entry in the rela.plt section.  */
+	  rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT);
+	  rela.r_addend = 0;
+	  loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela);
+	  bed->s->swap_reloca_out (output_bfd, &rela, loc);
+	}
 
       if (!h->def_regular)
 	{
-- 
2.31.1


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 5/5 v1] LoongArch: Delete R_LARCH_NONE from dynamic info.
  2022-07-18  8:43 [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types liuzhensong
                   ` (2 preceding siblings ...)
  2022-07-18  8:43 ` [PATCH 4/5 v1] LoongArch: Move ifunc info to rela.dyn from rela.plt liuzhensong
@ 2022-07-18  8:43 ` liuzhensong
  2022-07-18 10:06 ` [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types WANG Xuerui
  2022-07-19  4:29 ` Xi Ruoyao
  5 siblings, 0 replies; 24+ messages in thread
From: liuzhensong @ 2022-07-18  8:43 UTC (permalink / raw)
  To: binutils; +Cc: xuchenghua, mengqinggang, liuzhensong

  Some R_LARCH_64 in section .eh_frame will to generate
  R_LARCH_NONE, we change relocation to R_LARCH_32_PCREL
  from R_LARCH_64 in setction .eh_frame and not generate
  dynamic relocation for R_LARCH_32_PCREL.

  Add New relocate type R_LARCH_32_PCREL for .eh_frame.

  include/elf/
    loongarch.h

  bfd/
    bfd/bfd-in2.h
    libbfd.h
    reloc.c
    elfxx-loongarch.c
    elfnn-loongarch.c

  gas/config/
    tc-loongarch.c

  binutils/
    readelf.c

  ld/testsuite/ld-elf/
    eh5.d
---
 bfd/bfd-in2.h             |  1 +
 bfd/elfnn-loongarch.c     | 11 +++++++++++
 bfd/elfxx-loongarch.c     | 19 ++++++++++++++++++-
 bfd/libbfd.h              |  1 +
 bfd/reloc.c               |  3 +++
 binutils/readelf.c        |  2 ++
 include/elf/loongarch.h   |  5 ++++-
 ld/testsuite/ld-elf/eh5.d |  2 +-
 8 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index a71b3e82057..53abf36477f 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6309,6 +6309,7 @@ assembler and not (currently) written to any object files.  */
   BFD_RELOC_LARCH_TLS_LD64_HI20,
   BFD_RELOC_LARCH_TLS_GD_PC_HI20,
   BFD_RELOC_LARCH_TLS_GD64_HI20,
+  BFD_RELOC_LARCH_32_PCREL,
   BFD_RELOC_LARCH_RELAX,
   BFD_RELOC_UNUSED };
 
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 5bb7596e5d0..44b8d6dca9b 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -2011,6 +2011,17 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
       bfd_put (bits, input_bfd, opr1 - value, contents + rel->r_offset);
       break;
 
+    /* For eh_frame and debug info.  */
+    case R_LARCH_32_PCREL:
+      value -= sec_addr (input_section) + rel->r_offset;
+      value += rel->r_addend;
+      bfd_vma word = bfd_get (howto->bitsize, input_bfd,
+			      contents + rel->r_offset);
+      word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
+      bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
+      r = bfd_reloc_ok;
+      break;
+
     /* New reloc type.
        R_LARCH_B16 ~ R_LARCH_TLS_GD64_HI20.  */
     case R_LARCH_B16:
diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
index 1f6346ef5f3..1a4f99a8927 100644
--- a/bfd/elfxx-loongarch.c
+++ b/bfd/elfxx-loongarch.c
@@ -1327,7 +1327,24 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 reloc_bits,				/* adjust_reloc_bits */
 	 "gd64_hi20"),				/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_RELAX,		/* type (99).  */
+  LOONGARCH_HOWTO (R_LARCH_32_PCREL,		/* type (99).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 32,					/* bitsize.  */
+	 true,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_32_PCREL",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0xffffffff,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_32_PCREL,		/* bfd_reloc_code_real_type */
+	 NULL,					/* adjust_reloc_bits */
+	 NULL),					/* larch_reloc_type_name */
+
+  LOONGARCH_HOWTO (R_LARCH_RELAX,		/* type (100).  */
 	 0,					/* rightshift */
 	 1,					/* size */
 	 0,					/* bitsize */
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index b23ae4b755c..0b8610524e1 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -3492,6 +3492,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_LARCH_TLS_LD64_HI20",
   "BFD_RELOC_LARCH_TLS_GD_PC_HI20",
   "BFD_RELOC_LARCH_TLS_GD64_HI20",
+  "BFD_RELOC_LARCH_32_PCREL",
   "BFD_RELOC_LARCH_RELAX",
  "@@overflow: BFD_RELOC_UNUSED@@",
 };
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 836fa162108..6f092235369 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -8304,6 +8304,9 @@ ENUMX
 ENUMX
   BFD_RELOC_LARCH_TLS_GD64_HI20
 
+ENUMX
+  BFD_RELOC_LARCH_32_PCREL
+
 ENUMX
   BFD_RELOC_LARCH_RELAX
 
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 0f5977bc072..74f59d49fdc 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -14388,6 +14388,8 @@ is_32bit_pcrel_reloc (Filedata * filedata, unsigned int reloc_type)
     case EM_AVR_OLD:
     case EM_AVR:
       return reloc_type == 36; /* R_AVR_32_PCREL.  */
+    case EM_LOONGARCH:
+      return reloc_type == 99;  /* R_LARCH_32_PCREL.  */
     case EM_MICROBLAZE:
       return reloc_type == 2;  /* R_MICROBLAZE_32_PCREL.  */
     case EM_OR1K:
diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h
index 863dad3a371..9e0a5217f60 100644
--- a/include/elf/loongarch.h
+++ b/include/elf/loongarch.h
@@ -223,8 +223,11 @@ RELOC_NUMBER (R_LARCH_TLS_GD_PC_HI20, 97)
    %gd64_hi20 (sym).  */
 RELOC_NUMBER (R_LARCH_TLS_GD64_HI20, 98)
 
+/* For eh_frame and debug info.  */
+RELOC_NUMBER (R_LARCH_32_PCREL, 99)
+
 /* RELAX.  */
-RELOC_NUMBER (R_LARCH_RELAX, 99)
+RELOC_NUMBER (R_LARCH_RELAX, 100)
 
 END_RELOC_NUMBERS (R_LARCH_count)
 
diff --git a/ld/testsuite/ld-elf/eh5.d b/ld/testsuite/ld-elf/eh5.d
index d614251587c..4a697482355 100644
--- a/ld/testsuite/ld-elf/eh5.d
+++ b/ld/testsuite/ld-elf/eh5.d
@@ -4,7 +4,7 @@
 #ld:
 #readelf: -wf
 #target: [check_as_cfi]
-#xfail: alpha-*-*ecoff hppa64-*-* tile*-*-* visium-*-* loongarch64-*-*
+#xfail: alpha-*-*ecoff hppa64-*-* tile*-*-* visium-*-*
 
 Contents of the .eh_frame section:
 
-- 
2.31.1


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-18  8:43 [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types liuzhensong
                   ` (3 preceding siblings ...)
  2022-07-18  8:43 ` [PATCH 5/5 v1] LoongArch: Delete R_LARCH_NONE from dynamic info liuzhensong
@ 2022-07-18 10:06 ` WANG Xuerui
  2022-07-18 11:33   ` Xi Ruoyao
                     ` (2 more replies)
  2022-07-19  4:29 ` Xi Ruoyao
  5 siblings, 3 replies; 24+ messages in thread
From: WANG Xuerui @ 2022-07-18 10:06 UTC (permalink / raw)
  To: liuzhensong, binutils; +Cc: xuchenghua, mengqinggang, Xi Ruoyao, Fangrui Song

(Adding Ruoyao and MaskRay to CC, who might be interested in this 
development as well, as it concerns the linker implementation.)


On 2022/7/18 16:43, liuzhensong wrote:

> This is the v1 version of patches to support new relocs for LoongArch.
>
> The new reloc types docnments are on:
> https://github.com/loongson/LoongArch-Documentation/pull/57/files
>
> The testsuite status:
>
>                  === binutils Summary ===
>                                                                                   
> # of expected passes            241
> # of unsupported tests          6
>
>                  === gas Summary ===
>                                                                                   
> # of expected passes            270
> # of unsupported tests          7
>
>                  === ld Summary ===
>                                                                                   
> # of expected passes            1457
> # of expected failures          11
> # of untested testcases         1
> # of unsupported tests          154
>
I assume the content above are the "cover letter".

BTW: you can generate a proper patch series with `git format-patch -vN 
--cover-letter <base>`; I think the mails in this series were manually 
edited by you since the "v1" is wrongly placed (it's usually "[PATCH vN 
NN/NN]").

>    Add new reloc types support, the new relocate type
>    definition depends which operation needs of linker.
"Define new reloc types according to linker needs" could be enough.
>
>
> ---
>   bfd/bfd-in2.h           |   36 ++
>   bfd/elfnn-loongarch.c   | 1194 ++++++++++++++++++++++------------
>   bfd/elfxx-loongarch.c   | 1354 +++++++++++++++++++++++++++++----------
>   bfd/elfxx-loongarch.h   |    4 +
>   bfd/libbfd.h            |   36 ++
>   bfd/reloc.c             |   79 +++
>   include/elf/loongarch.h |  142 +++-
>   7 files changed, 2095 insertions(+), 750 deletions(-)
>
> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
> index 4e1182e93d4..a71b3e82057 100644
> --- a/bfd/bfd-in2.h
> +++ b/bfd/bfd-in2.h
> @@ -6274,6 +6274,42 @@ assembler and not (currently) written to any object files.  */
>     BFD_RELOC_LARCH_SUB24,
>     BFD_RELOC_LARCH_SUB32,
>     BFD_RELOC_LARCH_SUB64,
> +  BFD_RELOC_LARCH_B16,
> +  BFD_RELOC_LARCH_B21,
> +  BFD_RELOC_LARCH_B26,
> +  BFD_RELOC_LARCH_ABS_HI20,
> +  BFD_RELOC_LARCH_ABS_LO12,
> +  BFD_RELOC_LARCH_ABS64_LO20,
> +  BFD_RELOC_LARCH_ABS64_HI12,
> +  BFD_RELOC_LARCH_PCALA_HI20,
> +  BFD_RELOC_LARCH_PCALA_LO12,
> +  BFD_RELOC_LARCH_PCALA64_LO20,
> +  BFD_RELOC_LARCH_PCALA64_HI12,
> +  BFD_RELOC_LARCH_GOT_PC_HI20,
> +  BFD_RELOC_LARCH_GOT_PC_LO12,
> +  BFD_RELOC_LARCH_GOT64_PC_LO20,
> +  BFD_RELOC_LARCH_GOT64_PC_HI12,
> +  BFD_RELOC_LARCH_GOT64_HI20,
> +  BFD_RELOC_LARCH_GOT64_LO12,
> +  BFD_RELOC_LARCH_GOT64_LO20,
> +  BFD_RELOC_LARCH_GOT64_HI12,
> +  BFD_RELOC_LARCH_TLS_LE_HI20,
> +  BFD_RELOC_LARCH_TLS_LE_LO12,
> +  BFD_RELOC_LARCH_TLS_LE64_LO20,
> +  BFD_RELOC_LARCH_TLS_LE64_HI12,
> +  BFD_RELOC_LARCH_TLS_IE_PC_HI20,
> +  BFD_RELOC_LARCH_TLS_IE_PC_LO12,
> +  BFD_RELOC_LARCH_TLS_IE64_PC_LO20,
> +  BFD_RELOC_LARCH_TLS_IE64_PC_HI12,
> +  BFD_RELOC_LARCH_TLS_IE64_HI20,
> +  BFD_RELOC_LARCH_TLS_IE64_LO12,
> +  BFD_RELOC_LARCH_TLS_IE64_LO20,
> +  BFD_RELOC_LARCH_TLS_IE64_HI12,
> +  BFD_RELOC_LARCH_TLS_LD_PC_HI20,
> +  BFD_RELOC_LARCH_TLS_LD64_HI20,
> +  BFD_RELOC_LARCH_TLS_GD_PC_HI20,
> +  BFD_RELOC_LARCH_TLS_GD64_HI20,

I think I've voiced my concerns over the naming of these ops multiple 
times already; the primary comment ([1]; in English) was posted back in 
May but no one in your team responded.

Reproducing the content (and adjusting a little) here:


Overall in a good direction (and IMHO the direction everyone should have 
taken in the first place), thanks! A few suggestions though:

Some of the names can be a bit hard to understand, for example ABS_LO12, 
ABS_HI20, ABS64_LO20 and ABS64_HI12; these are ambiguous on a first 
look, do you use the latter two instead of the former for 64-bit 
absolute relocs? (The answer is "no"; you use all 4. The latter two 
actually express the higher 32-bit half.)

After having trained your intuition to work in "the Loongson way", 
you'll then have to mentally add the "lower/higher half" and "width" 
together to get a picture of the bit-field being expressed. It could be 
better to somehow directly show the 0(LO)/12/32/52 inside those names.

Plus, currently it's implied that a particular relocation type is 
somehow bound to a specific instruction, that's being used by the 
reference implementation (binutils) for the type today. This is being a 
bit too specific, and could change, as future instructions emerge with 
similar or identical format. (BTW no one really understand what "ALA" 
means in "PCALA"; the insn is named "PCALAU12I", the "U12I" part is 
similar to "LU12I.W" thus understandable, and PC is obvious, but no 
explanation for "ALA" exists anywhere). It's better to express the 
"destination" not in terms of instruction names or vague 
"LO12/HI20/LO20/HI12" specifiers, but in terms of actual *instruction 
word slots* being filled. This way it's immediately obvious for anyone 
what place in the insn word the reloc is going to write to, without 
having to dig into actual linker code. However, you don't officially 
have a naming scheme for these, so I guess that's why you have to invent 
names (and be different with others & prior work).

I have drafted my scheme back in November 2021, which I posted at [2] a 
while ago; the approach is extremely similar (IMO there's only one 
possible way to implement the more traditional scheme), but my version 
has adopted the operand slot naming scheme of loongarch-opcodes ([3]; 
the convention document is edited and posted at [4] for inclusion in 
official LoongArch docs collection) and the more direct LO/12/32/52 
names for bit-field offsets (width is implied by the destination slot). 
Hope this would be useful.


Again, I may sound like a bikeshedder, but IMO better names benefit 
everyone in the long term. I for one definitely don't want to see all 
four of "LO12/HI20/LO20/HI12" (they refer to the two 32-bit halves of a 
64-bit value, not two ways to segment one 32-bit value), nor 
"B16/B21/B26" (which are more different than you might think).

[1]: https://github.com/loongson/LoongArch-Documentation/pull/50
[2]: 
https://github.com/loongson/binutils-gdb/issues/134#issuecomment-1110510582
[3]: https://github.com/loongson-community/loongarch-opcodes
[4]: https://github.com/loongson/LoongArch-Documentation/pull/56


FYI, I did make a list of my suggested names for these reloc types 
("BFD_RELOC_LARCH_" abbreviated to "B_R_L_"):

Original name           Suggested name
-------------           --------------
B_R_L_B16               B_R_L_PCREL_SK16 *1
B_R_L_B21               B_R_L_PCREL_SD5K16
B_R_L_B26               B_R_L_PCREL_SD10K16
B_R_L_ABS_LO12          B_R_L_ABS_0_SK12
B_R_L_ABS_HI20          B_R_L_ABS_12_SJ20
B_R_L_ABS64_LO20        B_R_L_ABS_32_SJ20
B_R_L_ABS64_HI12        B_R_L_ABS_52_SK12
B_R_L_PCALA_LO12        B_R_L_PCALA_0_SK12 *2
B_R_L_PCALA_HI20        B_R_L_PCALA_12_SJ20
B_R_L_PCALA64_LO20      B_R_L_PCALA_32_SJ20 *3
B_R_L_PCALA64_HI12      B_R_L_PCALA_52_SK12
B_R_L_GOT_PC_LO12       B_R_L_GOT_PCALA_0_SK12 *4
B_R_L_GOT_PC_HI20       B_R_L_GOT_PCALA_12_SJ20
B_R_L_GOT64_PC_LO20     B_R_L_GOT_PCALA_32_SJ20
B_R_L_GOT64_PC_HI12     B_R_L_GOT_PCALA_52_SK12
B_R_L_GOT64_LO12        B_R_L_GOT_ABS_0_SK12 *5
B_R_L_GOT64_HI20        B_R_L_GOT_ABS_12_SJ20
B_R_L_GOT64_LO20        B_R_L_GOT_ABS_32_SJ20
B_R_L_GOT64_HI12        B_R_L_GOT_ABS_52_SK12
B_R_L_TLS_LE_LO12       B_R_L_TLS_LE_ABS_0_SK12
B_R_L_TLS_LE_HI20       B_R_L_TLS_LE_ABS_12_SJ20
B_R_L_TLS_LE64_LO20     B_R_L_TLS_LE_ABS_32_SJ20
B_R_L_TLS_LE64_HI12     B_R_L_TLS_LE_ABS_52_SK12
B_R_L_TLS_IE_PC_LO12    B_R_L_TLS_IE_PCALA_0_SK12
B_R_L_TLS_IE_PC_HI20    B_R_L_TLS_IE_PCALA_12_SJ20
B_R_L_TLS_IE64_PC_LO20  B_R_L_TLS_IE_PCALA_32_SJ20
B_R_L_TLS_IE64_PC_HI12  B_R_L_TLS_IE_PCALA_52_SK12
B_R_L_TLS_IE64_LO12     B_R_L_TLS_IE_ABS_0_SK12
B_R_L_TLS_IE64_HI20     B_R_L_TLS_IE_ABS_12_SJ20
B_R_L_TLS_IE64_LO20     B_R_L_TLS_IE_ABS_32_SJ20
B_R_L_TLS_IE64_HI12     B_R_L_TLS_IE_ABS_52_SK12
B_R_L_TLS_LD_PC_HI20    B_R_L_TLS_LD_PCALA_12_SJ20 *6
B_R_L_TLS_LD64_HI20     B_R_L_TLS_LD_ABS_12_SJ20
B_R_L_TLS_GD_PC_HI20    B_R_L_TLS_GD_PCALA_12_SJ20
B_R_L_TLS_GD64_HI20     B_R_L_TLS_GD_ABS_12_SJ20

*1 PCREL is explicitly called out. As you can see, every reloc type 
looks like "<purpose>_<starting bit position>_<destination slot>".
*2 I've reordered the types so that in each group of 4 reloc types it's 
always from LSB to MSB. And while I don't know what "PCALA" means, I've 
kept them all, and distinct from "PCREL" because the jumps and PCADDU12I 
don't clear the lowest 12 bits of destination, thus immediates for use 
with PCALAU12I needs to be differentiated.
*3 With the starting bit position explicit called out, no "64" 
distinction needs to be made.
*4 This (and others) actually uses the PCALAU12I, so should be named 
accordingly.
*5 This (and others) seems like an absolute reloc (it uses the same 
LU12I.W + xxx + LU32I.D + LU52I.D sequence), so ABS is added to name.
*6 I can't immediately make sense of the last 4 reloc types, but I've 
renamed these too. I would have to dig deeper for understanding the 
expected use case.

And I hope with this proposal, the (bikeshedding) discussion could be 
well-founded and constructive.

> +  BFD_RELOC_LARCH_RELAX,
I see this is just being reserved but without any actual behavior 
specified. Is it better to just leave it out for now?

<snip>

>   
>   /* Processor specific flags for the ELF header e_flags field.  */
> @@ -102,9 +238,9 @@ END_RELOC_NUMBERS (R_LARCH_count)
>   #define EF_LOONGARCH_ABI_ILP32_SINGLE_FLOAT	0x6
>   #define EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT	0x7
>   
> -#define EF_LOONGARCH_ABI_MASK	    		0x7
> -#define EF_LOONGARCH_ABI_ILP32_MASK	    	0x4
> -#define EF_LOONGARCH_ABI_FLOAT_MASK	    	0x3
> +#define EF_LOONGARCH_ABI_MASK			0x7
> +#define EF_LOONGARCH_ABI_ILP32_MASK		0x4
> +#define EF_LOONGARCH_ABI_FLOAT_MASK		0x3
>   #define EF_LOONGARCH_ABI_SOFT_FLOAT_MASK	0x1
>   #define EF_LOONGARCH_ABI_SINGLE_FLOAT_MASK	0x2
>   #define EF_LOONGARCH_ABI_DOUBLE_FLOAT_MASK	0x3
This hunk looks like pure cosmetic change, could this be split out (and 
get committed very quickly unlike the other major changes)?

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-18 10:06 ` [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types WANG Xuerui
@ 2022-07-18 11:33   ` Xi Ruoyao
  2022-07-18 12:11     ` WANG Xuerui
  2022-07-19  7:32   ` liuzhensong
  2022-07-20  2:42   ` liuzhensong
  2 siblings, 1 reply; 24+ messages in thread
From: Xi Ruoyao @ 2022-07-18 11:33 UTC (permalink / raw)
  To: WANG Xuerui, liuzhensong, binutils; +Cc: xuchenghua, mengqinggang, Fangrui Song

On Mon, 2022-07-18 at 18:06 +0800, WANG Xuerui wrote:
> (Adding Ruoyao and MaskRay to CC, who might be interested in this 
> development as well, as it concerns the linker implementation.)

I've already subscribed binutils@sourceware.org in order not to be
passed by.

> I think I've voiced my concerns over the naming of these ops multiple 
> times already; the primary comment ([1]; in English) was posted back in 
> May but no one in your team responded.
> 
> Reproducing the content (and adjusting a little) here:
> 
> 
> Overall in a good direction (and IMHO the direction everyone should have 
> taken in the first place), thanks!
> 

Yes, we've been paying additional costs using those "stack based
relocation".  I'd like to know why they were proposed in first place? 
(Not accusing anyone, just my curiosity: AFAIK no other targets ever
used such a stack for relocation.)

/* snip */


> FYI, I did make a list of my suggested names for these reloc types 
> ("BFD_RELOC_LARCH_" abbreviated to "B_R_L_"):
> 
> Original name           Suggested name
> -------------           --------------
> B_R_L_B16               B_R_L_PCREL_SK16 *1
> B_R_L_B21               B_R_L_PCREL_SD5K16
> B_R_L_B26               B_R_L_PCREL_SD10K16
> B_R_L_ABS_LO12          B_R_L_ABS_0_SK12
> B_R_L_ABS_HI20          B_R_L_ABS_12_SJ20
> B_R_L_ABS64_LO20        B_R_L_ABS_32_SJ20
> B_R_L_ABS64_HI12        B_R_L_ABS_52_SK12
> B_R_L_PCALA_LO12        B_R_L_PCALA_0_SK12 *2
> B_R_L_PCALA_HI20        B_R_L_PCALA_12_SJ20
> B_R_L_PCALA64_LO20      B_R_L_PCALA_32_SJ20 *3
> B_R_L_PCALA64_HI12      B_R_L_PCALA_52_SK12
> B_R_L_GOT_PC_LO12       B_R_L_GOT_PCALA_0_SK12 *4
> B_R_L_GOT_PC_HI20       B_R_L_GOT_PCALA_12_SJ20
> B_R_L_GOT64_PC_LO20     B_R_L_GOT_PCALA_32_SJ20
> B_R_L_GOT64_PC_HI12     B_R_L_GOT_PCALA_52_SK12
> B_R_L_GOT64_LO12        B_R_L_GOT_ABS_0_SK12 *5
> B_R_L_GOT64_HI20        B_R_L_GOT_ABS_12_SJ20
> B_R_L_GOT64_LO20        B_R_L_GOT_ABS_32_SJ20
> B_R_L_GOT64_HI12        B_R_L_GOT_ABS_52_SK12
> B_R_L_TLS_LE_LO12       B_R_L_TLS_LE_ABS_0_SK12
> B_R_L_TLS_LE_HI20       B_R_L_TLS_LE_ABS_12_SJ20
> B_R_L_TLS_LE64_LO20     B_R_L_TLS_LE_ABS_32_SJ20
> B_R_L_TLS_LE64_HI12     B_R_L_TLS_LE_ABS_52_SK12
> B_R_L_TLS_IE_PC_LO12    B_R_L_TLS_IE_PCALA_0_SK12
> B_R_L_TLS_IE_PC_HI20    B_R_L_TLS_IE_PCALA_12_SJ20
> B_R_L_TLS_IE64_PC_LO20  B_R_L_TLS_IE_PCALA_32_SJ20
> B_R_L_TLS_IE64_PC_HI12  B_R_L_TLS_IE_PCALA_52_SK12
> B_R_L_TLS_IE64_LO12     B_R_L_TLS_IE_ABS_0_SK12
> B_R_L_TLS_IE64_HI20     B_R_L_TLS_IE_ABS_12_SJ20
> B_R_L_TLS_IE64_LO20     B_R_L_TLS_IE_ABS_32_SJ20
> B_R_L_TLS_IE64_HI12     B_R_L_TLS_IE_ABS_52_SK12
> B_R_L_TLS_LD_PC_HI20    B_R_L_TLS_LD_PCALA_12_SJ20 *6
> B_R_L_TLS_LD64_HI20     B_R_L_TLS_LD_ABS_12_SJ20
> B_R_L_TLS_GD_PC_HI20    B_R_L_TLS_GD_PCALA_12_SJ20
> B_R_L_TLS_GD64_HI20     B_R_L_TLS_GD_ABS_12_SJ20

It's overall better, but those "J, K" etc are cryptic IMHO.  And for
"B_R_L_B16" I think "B_R_L_PCREL_SK16" fails to express that the offset
should be shifted right by 2, so I'd keep B_R_L_B16 (and similarly,
B_R_L_B21 and B_R_L_B26) like the PCALA case.

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 4/5 v1] LoongArch: Move ifunc info to rela.dyn from rela.plt.
  2022-07-18  8:43 ` [PATCH 4/5 v1] LoongArch: Move ifunc info to rela.dyn from rela.plt liuzhensong
@ 2022-07-18 11:45   ` Xi Ruoyao
  2022-07-18 16:27   ` Xi Ruoyao
  1 sibling, 0 replies; 24+ messages in thread
From: Xi Ruoyao @ 2022-07-18 11:45 UTC (permalink / raw)
  To: liuzhensong, binutils; +Cc: xuchenghua, mengqinggang, WANG Xuerui

On Mon, 2022-07-18 at 16:43 +0800, liuzhensong wrote:
>   Delete R_LARCH_IRELATIVE from dynamic loader (glibc ld.so) when
>   loading lazy function (rela.plt section).
> 
>   In dynamic programes, move ifunc dynamic relocate info to section
>   srelgot from srelplt.
> 
>   bfd/
>     elfnn-loongarch.c
> ---
>  bfd/elfnn-loongarch.c | 322 ++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 310 insertions(+), 12 deletions(-)
> 
> diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
> index 4eeaeb44eff..5bb7596e5d0 100644
> --- a/bfd/elfnn-loongarch.c
> +++ b/bfd/elfnn-loongarch.c
> @@ -1207,6 +1207,259 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
>    return true;
>  }
>  
> +/* Based function _bfd_elf_allocate_ifunc_dyn_relocs.

"A modified version of _bfd_elf_allocate_ifunc_dyn_relocs."

> +   For local def and ref ifunc,
> +   dynamic relocations are stored in
> +   1.  rel[a].irelifunc section in PIC object.
> +   2.  rel[a].srelgot section in dynamic executable.
> +   3.  rel[a].irelplt section in static executable.

For entire patch, I think it's better to remove those "[]" around "a":
for LoongArch we always use .rela.*, not .rel.* .

> +   Change ifunc dynamic info from srelplt to srelgot.
> +   In loader, remove R_LARCH_IRELACTIVE from rela lazy in ld.so.  */

"Unlike _bfd_elf_allocate_ifunc_dyn_relocs, .rela.srelgot is used
instead of .rela.srelplt.  Glibc ELF loader will not support
R_LARCH_IRELATIVE relocation in .rela.plt."

My English is not good either, but the origin comment is obviously some
Chinglish.  Xuerui: can you help to reword the comments in this series?

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-18 11:33   ` Xi Ruoyao
@ 2022-07-18 12:11     ` WANG Xuerui
  2022-07-18 12:18       ` WANG Xuerui
                         ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: WANG Xuerui @ 2022-07-18 12:11 UTC (permalink / raw)
  To: Xi Ruoyao, WANG Xuerui, liuzhensong, binutils
  Cc: xuchenghua, mengqinggang, Fangrui Song

On 2022/7/18 19:33, Xi Ruoyao wrote:
> On Mon, 2022-07-18 at 18:06 +0800, WANG Xuerui wrote:
>> (Adding Ruoyao and MaskRay to CC, who might be interested in this
>> development as well, as it concerns the linker implementation.)
> I've already subscribed binutils@sourceware.org in order not to be
> passed by.
>
>> I think I've voiced my concerns over the naming of these ops multiple
>> times already; the primary comment ([1]; in English) was posted back in
>> May but no one in your team responded.
>>
>> Reproducing the content (and adjusting a little) here:
>>
>>
>> Overall in a good direction (and IMHO the direction everyone should have
>> taken in the first place), thanks!
>>
> Yes, we've been paying additional costs using those "stack based
> relocation".  I'd like to know why they were proposed in first place?
> (Not accusing anyone, just my curiosity: AFAIK no other targets ever
> used such a stack for relocation.)
As previously pointed out on this list, rx and rl78 both use stack-based 
relocs. (Both come from Renesas, so I do think it's delibrate design 
decision, but of course the original Renesas justification is most 
probably buried in history.) I explained this in 
https://github.com/loongson/binutils-gdb/issues/134 before.
>
> /* snip */
>
>
>> FYI, I did make a list of my suggested names for these reloc types
>> ("BFD_RELOC_LARCH_" abbreviated to "B_R_L_"):
>>
>> Original name           Suggested name
>> -------------           --------------
>> B_R_L_B16               B_R_L_PCREL_SK16 *1
>> B_R_L_B21               B_R_L_PCREL_SD5K16
>> B_R_L_B26               B_R_L_PCREL_SD10K16
>> B_R_L_ABS_LO12          B_R_L_ABS_0_SK12
>> B_R_L_ABS_HI20          B_R_L_ABS_12_SJ20
>> B_R_L_ABS64_LO20        B_R_L_ABS_32_SJ20
>> B_R_L_ABS64_HI12        B_R_L_ABS_52_SK12
>> B_R_L_PCALA_LO12        B_R_L_PCALA_0_SK12 *2
>> B_R_L_PCALA_HI20        B_R_L_PCALA_12_SJ20
>> B_R_L_PCALA64_LO20      B_R_L_PCALA_32_SJ20 *3
>> B_R_L_PCALA64_HI12      B_R_L_PCALA_52_SK12
>> B_R_L_GOT_PC_LO12       B_R_L_GOT_PCALA_0_SK12 *4
>> B_R_L_GOT_PC_HI20       B_R_L_GOT_PCALA_12_SJ20
>> B_R_L_GOT64_PC_LO20     B_R_L_GOT_PCALA_32_SJ20
>> B_R_L_GOT64_PC_HI12     B_R_L_GOT_PCALA_52_SK12
>> B_R_L_GOT64_LO12        B_R_L_GOT_ABS_0_SK12 *5
>> B_R_L_GOT64_HI20        B_R_L_GOT_ABS_12_SJ20
>> B_R_L_GOT64_LO20        B_R_L_GOT_ABS_32_SJ20
>> B_R_L_GOT64_HI12        B_R_L_GOT_ABS_52_SK12
>> B_R_L_TLS_LE_LO12       B_R_L_TLS_LE_ABS_0_SK12
>> B_R_L_TLS_LE_HI20       B_R_L_TLS_LE_ABS_12_SJ20
>> B_R_L_TLS_LE64_LO20     B_R_L_TLS_LE_ABS_32_SJ20
>> B_R_L_TLS_LE64_HI12     B_R_L_TLS_LE_ABS_52_SK12
>> B_R_L_TLS_IE_PC_LO12    B_R_L_TLS_IE_PCALA_0_SK12
>> B_R_L_TLS_IE_PC_HI20    B_R_L_TLS_IE_PCALA_12_SJ20
>> B_R_L_TLS_IE64_PC_LO20  B_R_L_TLS_IE_PCALA_32_SJ20
>> B_R_L_TLS_IE64_PC_HI12  B_R_L_TLS_IE_PCALA_52_SK12
>> B_R_L_TLS_IE64_LO12     B_R_L_TLS_IE_ABS_0_SK12
>> B_R_L_TLS_IE64_HI20     B_R_L_TLS_IE_ABS_12_SJ20
>> B_R_L_TLS_IE64_LO20     B_R_L_TLS_IE_ABS_32_SJ20
>> B_R_L_TLS_IE64_HI12     B_R_L_TLS_IE_ABS_52_SK12
>> B_R_L_TLS_LD_PC_HI20    B_R_L_TLS_LD_PCALA_12_SJ20 *6
>> B_R_L_TLS_LD64_HI20     B_R_L_TLS_LD_ABS_12_SJ20
>> B_R_L_TLS_GD_PC_HI20    B_R_L_TLS_GD_PCALA_12_SJ20
>> B_R_L_TLS_GD64_HI20     B_R_L_TLS_GD_ABS_12_SJ20
> It's overall better, but those "J, K" etc are cryptic IMHO.  And for
> "B_R_L_B16" I think "B_R_L_PCREL_SK16" fails to express that the offset
> should be shifted right by 2, so I'd keep B_R_L_B16 (and similarly,
> B_R_L_B21 and B_R_L_B26) like the PCALA case.
>
The slot names come from 
https://github.com/loongson/LoongArch-Documentation/pull/56 (to 
non-Chinese speakers: English translation still TODO, but hopefully at 
least the ABNF and the few tables should be intelligible even without 
translation).

As for the PCREL and implicit shifts, maybe a planned extension of the 
slot syntax could help. I plan to submit an Assembly Language Convention 
after the Instruction Format Convention gets reviewed and merged, and 
with this new convention such an extension is necessary anyway for 
accommodating the current assembly syntax as described by the ISA 
manual, able to express the <<2's and +1's for the PC-manipulating and 
ALSL insns.

For example, let's say the extension works like this: ordinary slot 
syntax, plus "p", plus an postprocess operator, with "s\d+" for "imm 
slot = assembly operand >> N", and "p\d+" for "imm slot = assembly 
operand + N". Then we could say "B_R_L_PCREL_SK16PS2" and have all the 
niceties. (In an ideal world, the LoongArch opcodes implementation 
should be modified to use this convention too, so for example it will be 
something like "DJSk16ps2" for JIRL, "JDSk16ps2" for BLT (notice the 
reversed operand order) and "DJKUa2pp1" for ALSL insns.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-18 12:11     ` WANG Xuerui
@ 2022-07-18 12:18       ` WANG Xuerui
  2022-07-19  3:57       ` Fangrui Song
  2022-07-20  2:07       ` liuzhensong
  2 siblings, 0 replies; 24+ messages in thread
From: WANG Xuerui @ 2022-07-18 12:18 UTC (permalink / raw)
  To: WANG Xuerui, Xi Ruoyao, liuzhensong, binutils
  Cc: xuchenghua, mengqinggang, Fangrui Song


On 2022/7/18 20:11, WANG Xuerui wrote:
> For example, let's say the extension works like this: ordinary slot 
> syntax, plus "p", plus an postprocess operator, with "s\d+" for "imm 
> slot = assembly operand >> N", and "p\d+" for "imm slot = assembly 
> operand + N".
Actually it's "imm slot = assembly operand - N" for the proposed "p\d+". 
It doesn't matter that much though, because ALSLs don't take part in 
relocation, it was just a side mention.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 4/5 v1] LoongArch: Move ifunc info to rela.dyn from rela.plt.
  2022-07-18  8:43 ` [PATCH 4/5 v1] LoongArch: Move ifunc info to rela.dyn from rela.plt liuzhensong
  2022-07-18 11:45   ` Xi Ruoyao
@ 2022-07-18 16:27   ` Xi Ruoyao
  2022-07-19  7:26     ` liuzhensong
  1 sibling, 1 reply; 24+ messages in thread
From: Xi Ruoyao @ 2022-07-18 16:27 UTC (permalink / raw)
  To: liuzhensong, binutils; +Cc: xuchenghua, mengqinggang, WANG Xuerui

On Mon, 2022-07-18 at 16:43 +0800, liuzhensong wrote:
>   Delete R_LARCH_IRELATIVE from dynamic loader (glibc ld.so) when
>   loading lazy function (rela.plt section).
> 
>   In dynamic programes, move ifunc dynamic relocate info to section
>   srelgot from srelplt.

The main point of this change is allowing us to enable ifunc support for
Glibc, right?

But have you tested building Glibc using a ld with this series applied?
It does not work well for me:

FAIL: elf/ifuncmain1
FAIL: elf/ifuncmain1pic
FAIL: elf/ifuncmain1pie
FAIL: elf/ifuncmain1staticpic
FAIL: elf/ifuncmain1staticpie
FAIL: elf/ifuncmain1vis
FAIL: elf/ifuncmain1vispic
FAIL: elf/ifuncmain1vispie
FAIL: elf/ifuncmain3
FAIL: elf/ifuncmain4
FAIL: elf/ifuncmain5staticpic
FAIL: elf/ifuncmain7
FAIL: elf/ifuncmain7pic
FAIL: elf/ifuncmain7pie

Note that Binutils test suite is far from complete.  For example, the
ifunc handling for LoongArch target in master branch (with or w/o this
patch) can pass all ld tests, but it just blows up with a simple test
case:

$ cat c.s
.global ifunc
.type ifunc, @gnu_indirect_function
.set ifunc, resolver

resolver:
  la.local $a0, impl
  jr $ra

impl:
  li.w $a0, 42
  jr $ra

.data
.global x
.type x, @object
x:
  .dword ifunc

$ cc c.s -shared
collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped
compilation terminated.

So I think you'll at least need to build kernel/glibc/gcc using a ld
with your patches to make sure it works correctly.
-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-18 12:11     ` WANG Xuerui
  2022-07-18 12:18       ` WANG Xuerui
@ 2022-07-19  3:57       ` Fangrui Song
  2022-07-20  7:47         ` liuzhensong
  2022-07-20  2:07       ` liuzhensong
  2 siblings, 1 reply; 24+ messages in thread
From: Fangrui Song @ 2022-07-19  3:57 UTC (permalink / raw)
  To: WANG Xuerui; +Cc: Xi Ruoyao, liuzhensong, binutils, xuchenghua, mengqinggang

On 2022-07-18, WANG Xuerui wrote:
>On 2022/7/18 19:33, Xi Ruoyao wrote:
>>On Mon, 2022-07-18 at 18:06 +0800, WANG Xuerui wrote:
>>>(Adding Ruoyao and MaskRay to CC, who might be interested in this
>>>development as well, as it concerns the linker implementation.)
>>I've already subscribed binutils@sourceware.org in order not to be
>>passed by.

I am subscribed, too. Direct CC helps me find the discussions:)

>>>I think I've voiced my concerns over the naming of these ops multiple
>>>times already; the primary comment ([1]; in English) was posted back in
>>>May but no one in your team responded.
>>>
>>>Reproducing the content (and adjusting a little) here:
>>>
>>>
>>>Overall in a good direction (and IMHO the direction everyone should have
>>>taken in the first place), thanks!
>>>
>>Yes, we've been paying additional costs using those "stack based
>>relocation".  I'd like to know why they were proposed in first place?
>>(Not accusing anyone, just my curiosity: AFAIK no other targets ever
>>used such a stack for relocation.)
>As previously pointed out on this list, rx and rl78 both use 
>stack-based relocs. (Both come from Renesas, so I do think it's 
>delibrate design decision, but of course the original Renesas 
>justification is most probably buried in history.) I explained this in 
>https://github.com/loongson/binutils-gdb/issues/134 before.

Stack machines aren't really suitable for ELF relocations.
Each relocation takes sizeof(Elf64_Rela) = 24 byte, higher than older
object file formats.

ELF32 allows 256 relocation types. There aren't too many to waste.

>>
>>/* snip */
>>
>>
>>>FYI, I did make a list of my suggested names for these reloc types
>>>("BFD_RELOC_LARCH_" abbreviated to "B_R_L_"):
>>>
>>>Original name           Suggested name
>>>-------------           --------------
>>>B_R_L_B16               B_R_L_PCREL_SK16 *1
>>>B_R_L_B21               B_R_L_PCREL_SD5K16
>>>B_R_L_B26               B_R_L_PCREL_SD10K16
>>>B_R_L_ABS_LO12          B_R_L_ABS_0_SK12
>>>B_R_L_ABS_HI20          B_R_L_ABS_12_SJ20
>>>B_R_L_ABS64_LO20        B_R_L_ABS_32_SJ20
>>>B_R_L_ABS64_HI12        B_R_L_ABS_52_SK12

aarch64 calls these G0/G1/G2/G3 while ppc calls these LO/HI/HIGHER/HIGHEST.
A name mentioning the offset and the length looks good to me, too.
A too-long name may have problems in the default (non-wide) output of
readelf -r.

>>>B_R_L_PCALA_LO12        B_R_L_PCALA_0_SK12 *2
>>>B_R_L_PCALA_HI20        B_R_L_PCALA_12_SJ20
>>>B_R_L_PCALA64_LO20      B_R_L_PCALA_32_SJ20 *3
>>>B_R_L_PCALA64_HI12      B_R_L_PCALA_52_SK12
>>>B_R_L_GOT_PC_LO12       B_R_L_GOT_PCALA_0_SK12 *4
>>>B_R_L_GOT_PC_HI20       B_R_L_GOT_PCALA_12_SJ20
>>>B_R_L_GOT64_PC_LO20     B_R_L_GOT_PCALA_32_SJ20
>>>B_R_L_GOT64_PC_HI12     B_R_L_GOT_PCALA_52_SK12
>>>B_R_L_GOT64_LO12        B_R_L_GOT_ABS_0_SK12 *5
>>>B_R_L_GOT64_HI20        B_R_L_GOT_ABS_12_SJ20
>>>B_R_L_GOT64_LO20        B_R_L_GOT_ABS_32_SJ20
>>>B_R_L_GOT64_HI12        B_R_L_GOT_ABS_52_SK12


>>>B_R_L_TLS_LE_LO12       B_R_L_TLS_LE_ABS_0_SK12
>>>B_R_L_TLS_LE_HI20       B_R_L_TLS_LE_ABS_12_SJ20
>>>B_R_L_TLS_LE64_LO20     B_R_L_TLS_LE_ABS_32_SJ20
>>>B_R_L_TLS_LE64_HI12     B_R_L_TLS_LE_ABS_52_SK12
>>>B_R_L_TLS_IE_PC_LO12    B_R_L_TLS_IE_PCALA_0_SK12
>>>B_R_L_TLS_IE_PC_HI20    B_R_L_TLS_IE_PCALA_12_SJ20
>>>B_R_L_TLS_IE64_PC_LO20  B_R_L_TLS_IE_PCALA_32_SJ20
>>>B_R_L_TLS_IE64_PC_HI12  B_R_L_TLS_IE_PCALA_52_SK12
>>>B_R_L_TLS_IE64_LO12     B_R_L_TLS_IE_ABS_0_SK12
>>>B_R_L_TLS_IE64_HI20     B_R_L_TLS_IE_ABS_12_SJ20
>>>B_R_L_TLS_IE64_LO20     B_R_L_TLS_IE_ABS_32_SJ20
>>>B_R_L_TLS_IE64_HI12     B_R_L_TLS_IE_ABS_52_SK12
>>>B_R_L_TLS_LD_PC_HI20    B_R_L_TLS_LD_PCALA_12_SJ20 *6
>>>B_R_L_TLS_LD64_HI20     B_R_L_TLS_LD_ABS_12_SJ20
>>>B_R_L_TLS_GD_PC_HI20    B_R_L_TLS_GD_PCALA_12_SJ20
>>>B_R_L_TLS_GD64_HI20     B_R_L_TLS_GD_ABS_12_SJ20

aarch64 relocation types are well named. It's obvious what suppress
overflow checking.

For LO12, I expect that there are two variants: one with overflow check,
the other without.

>>It's overall better, but those "J, K" etc are cryptic IMHO.  And for
>>"B_R_L_B16" I think "B_R_L_PCREL_SK16" fails to express that the offset
>>should be shifted right by 2, so I'd keep B_R_L_B16 (and similarly,
>>B_R_L_B21 and B_R_L_B26) like the PCALA case.
>>
>The slot names come from 
>https://github.com/loongson/LoongArch-Documentation/pull/56 (to 
>non-Chinese speakers: English translation still TODO, but hopefully at 
>least the ABNF and the few tables should be intelligible even without 
>translation).
>
>As for the PCREL and implicit shifts, maybe a planned extension of the 
>slot syntax could help. I plan to submit an Assembly Language 
>Convention after the Instruction Format Convention gets reviewed and 
>merged, and with this new convention such an extension is necessary 
>anyway for accommodating the current assembly syntax as described by 
>the ISA manual, able to express the <<2's and +1's for the 
>PC-manipulating and ALSL insns.
>
>For example, let's say the extension works like this: ordinary slot 
>syntax, plus "p", plus an postprocess operator, with "s\d+" for "imm 
>slot = assembly operand >> N", and "p\d+" for "imm slot = assembly 
>operand + N". Then we could say "B_R_L_PCREL_SK16PS2" and have all the 
>niceties. (In an ideal world, the LoongArch opcodes implementation 
>should be modified to use this convention too, so for example it will 
>be something like "DJSk16ps2" for JIRL, "JDSk16ps2" for BLT (notice 
>the reversed operand order) and "DJKUa2pp1" for ALSL insns.
>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-18  8:43 [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types liuzhensong
                   ` (4 preceding siblings ...)
  2022-07-18 10:06 ` [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types WANG Xuerui
@ 2022-07-19  4:29 ` Xi Ruoyao
  2022-07-19  5:40   ` Xi Ruoyao
  5 siblings, 1 reply; 24+ messages in thread
From: Xi Ruoyao @ 2022-07-19  4:29 UTC (permalink / raw)
  To: liuzhensong, binutils; +Cc: xuchenghua, mengqinggang, WANG Xuerui

On Mon, 2022-07-18 at 16:43 +0800, liuzhensong wrote:
> @@ -2427,7 +2453,7 @@ loongarch_elf_relocate_section (bfd *output_bfd,
> struct bfd_link_info *info,
>  
>           if (h != NULL)
>             {
> -             off = h->got.offset;
> +             off = h->got.offset & (~1);
>  
>               if (off == MINUS_ONE
>                   && h->type != STT_GNU_IFUNC)
> @@ -2455,79 +2481,76 @@ loongarch_elf_relocate_section (bfd
> *output_bfd, struct bfd_link_info *info,

This cannot be correct: after "off = h->got.offset & (~1)", how could
"off == MINUS_ONE" be true?

Either you calculated "off" wrong, or you should remove the dead code.

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-19  4:29 ` Xi Ruoyao
@ 2022-07-19  5:40   ` Xi Ruoyao
  2022-07-19  6:31     ` 刘振松
  0 siblings, 1 reply; 24+ messages in thread
From: Xi Ruoyao @ 2022-07-19  5:40 UTC (permalink / raw)
  To: liuzhensong, binutils; +Cc: xuchenghua, mengqinggang, WANG Xuerui

On Tue, 2022-07-19 at 12:29 +0800, Xi Ruoyao via Binutils wrote:
> On Mon, 2022-07-18 at 16:43 +0800, liuzhensong wrote:
> > @@ -2427,7 +2453,7 @@ loongarch_elf_relocate_section (bfd
> > *output_bfd,
> > struct bfd_link_info *info,
> >  
> >           if (h != NULL)
> >             {
> > -             off = h->got.offset;
> > +             off = h->got.offset & (~1);
> >  
> >               if (off == MINUS_ONE
> >                   && h->type != STT_GNU_IFUNC)
> > @@ -2455,79 +2481,76 @@ loongarch_elf_relocate_section (bfd
> > *output_bfd, struct bfd_link_info *info,
> 
> This cannot be correct: after "off = h->got.offset & (~1)", how could
> "off == MINUS_ONE" be true?
> 
> Either you calculated "off" wrong, or you should remove the dead code.

I guess you need the following changes.  With those changes Glibc ifunc
tests passed:

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 44b8d6dca9b..4d22ba037c8 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -2730,7 +2730,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	    {
 	      off = h->got.offset & (~1);
 
-	      if (off == MINUS_ONE
+	      if (h->got.offset == MINUS_ONE
 		  && h->type != STT_GNU_IFUNC)
 		{
 		  fatal = (loongarch_reloc_is_fatal
@@ -2742,7 +2742,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
 	      /* Hidden symbol not has .got entry, only .got.plt entry
 		 so gprel is (plt - got).  */
-	      if (off == MINUS_ONE
+	      if (h->got.offset == MINUS_ONE
 		  && h->type == STT_GNU_IFUNC)
 		{
 		  if (h->plt.offset == (bfd_vma) -1)

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-19  5:40   ` Xi Ruoyao
@ 2022-07-19  6:31     ` 刘振松
  2022-07-19  6:34       ` Xi Ruoyao
  0 siblings, 1 reply; 24+ messages in thread
From: 刘振松 @ 2022-07-19  6:31 UTC (permalink / raw)
  To: Xi Ruoyao; +Cc: binutils, xuchenghua, mengqinggang, WANG Xuerui




&gt; -----原始邮件-----
&gt; 发件人: "Xi Ruoyao" <xry111@xry111.site>
&gt; 发送时间: 2022-07-19 13:40:02 (星期二)
&gt; 收件人: liuzhensong <liuzhensong@loongson.cn>, binutils@sourceware.org
&gt; 抄送: xuchenghua@loongson.cn, mengqinggang@loongson.cn, "WANG Xuerui" <i.swmail@xen0n.name>
&gt; 主题: Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
&gt; 
&gt; On Tue, 2022-07-19 at 12:29 +0800, Xi Ruoyao via Binutils wrote:
&gt; &gt; On Mon, 2022-07-18 at 16:43 +0800, liuzhensong wrote:
&gt; &gt; &gt; @@ -2427,7 +2453,7 @@ loongarch_elf_relocate_section (bfd
&gt; &gt; &gt; *output_bfd,
&gt; &gt; &gt; struct bfd_link_info *info,
&gt; &gt; &gt; &nbsp;
&gt; &gt; &gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (h != NULL)
&gt; &gt; &gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&gt; &gt; &gt; -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; off = h-&gt;got.offset;
&gt; &gt; &gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; off = h-&gt;got.offset &amp; (~1);
&gt; &gt; &gt; &nbsp;
&gt; &gt; &gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (off == MINUS_ONE
&gt; &gt; &gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; h-&gt;type != STT_GNU_IFUNC)
&gt; &gt; &gt; @@ -2455,79 +2481,76 @@ loongarch_elf_relocate_section (bfd
&gt; &gt; &gt; *output_bfd, struct bfd_link_info *info,
&gt; &gt; 
&gt; &gt; This cannot be correct: after "off = h-&gt;got.offset &amp; (~1)", how could
&gt; &gt; "off == MINUS_ONE" be true?
&gt; &gt; 
&gt; &gt; Either you calculated "off" wrong, or you should remove the dead code.
&gt; 
&gt; I guess you need the following changes.  With those changes Glibc ifunc
&gt; tests passed:
&gt; 
&gt; diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
&gt; index 44b8d6dca9b..4d22ba037c8 100644
&gt; --- a/bfd/elfnn-loongarch.c
&gt; +++ b/bfd/elfnn-loongarch.c
&gt; @@ -2730,7 +2730,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
&gt;  	    {
&gt;  	      off = h-&gt;got.offset &amp; (~1);
&gt;  
&gt; -	      if (off == MINUS_ONE
&gt; +	      if (h-&gt;got.offset == MINUS_ONE
&gt;  		  &amp;&amp; h-&gt;type != STT_GNU_IFUNC)
&gt;  		{
&gt;  		  fatal = (loongarch_reloc_is_fatal
&gt; @@ -2742,7 +2742,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
&gt;  
&gt;  	      /* Hidden symbol not has .got entry, only .got.plt entry
&gt;  		 so gprel is (plt - got).  */
&gt; -	      if (off == MINUS_ONE
&gt; +	      if (h-&gt;got.offset == MINUS_ONE
&gt;  		  &amp;&amp; h-&gt;type == STT_GNU_IFUNC)
&gt;  		{
&gt;  		  if (h-&gt;plt.offset == (bfd_vma) -1)
&gt; 
&gt; -- 
&gt; Xi Ruoyao <xry111@xry111.site>
&gt; School of Aerospace Science and Technology, Xidian University

Thanks for reviews.

Your modification is correct, this code valid for R_LARCH_SOP_PUSH_GPREL.
I have tested glibc testcases, there is no failed testcase about ifunc, does your environment generate new relocations?

Results of glibc with test args "make check subdirs=elf".
UNSUPPORTED: elf/tst-env-setuid
UNSUPPORTED: elf/tst-env-setuid-tunables
XPASS: elf/tst-protected1a
XPASS: elf/tst-protected1b
UNSUPPORTED: elf/tst-valgrind-smoke
Summary of test results:
    312 PASS
      3 UNSUPPORTED
      2 XPASS</xry111@xry111.site></i.swmail@xen0n.name></liuzhensong@loongson.cn></xry111@xry111.site>

本邮件及其附件含有龙芯中科的商业秘密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制或散发)本邮件及其附件中的信息。如果您错收本邮件,请您立即电话或邮件通知发件人并删除本邮件。 
This email and its attachments contain confidential information from Loongson Technology , which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this email in error, please notify the sender by phone or email immediately and delete it. 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-19  6:31     ` 刘振松
@ 2022-07-19  6:34       ` Xi Ruoyao
  0 siblings, 0 replies; 24+ messages in thread
From: Xi Ruoyao @ 2022-07-19  6:34 UTC (permalink / raw)
  To: 刘振松; +Cc: binutils, xuchenghua, mengqinggang, WANG Xuerui

On Tue, 2022-07-19 at 14:31 +0800, 刘振松 wrote:

> Your modification is correct, this code valid for
> R_LARCH_SOP_PUSH_GPREL.
> I have tested glibc testcases, there is no failed testcase about
> ifunc, does your environment generate new relocations?

I guess it's because I only installed new ld (make install-ld), without
new as.  So my as still generates R_LARCH_SOP_PUSH_GPREL.

> Results of glibc with test args "make check subdirs=elf".
> UNSUPPORTED: elf/tst-env-setuid
> UNSUPPORTED: elf/tst-env-setuid-tunables
> XPASS: elf/tst-protected1a
> XPASS: elf/tst-protected1b
> UNSUPPORTED: elf/tst-valgrind-smoke

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 4/5 v1] LoongArch: Move ifunc info to rela.dyn from rela.plt.
  2022-07-18 16:27   ` Xi Ruoyao
@ 2022-07-19  7:26     ` liuzhensong
  0 siblings, 0 replies; 24+ messages in thread
From: liuzhensong @ 2022-07-19  7:26 UTC (permalink / raw)
  To: Xi Ruoyao, binutils; +Cc: xuchenghua, mengqinggang, WANG Xuerui


在 2022/7/19 上午12:27, Xi Ruoyao 写道:
> On Mon, 2022-07-18 at 16:43 +0800, liuzhensong wrote:
>>    Delete R_LARCH_IRELATIVE from dynamic loader (glibc ld.so) when
>>    loading lazy function (rela.plt section).
>>
>>    In dynamic programes, move ifunc dynamic relocate info to section
>>    srelgot from srelplt.
> The main point of this change is allowing us to enable ifunc support for
> Glibc, right?
>
> But have you tested building Glibc using a ld with this series applied?
> It does not work well for me:
>
> FAIL: elf/ifuncmain1
> FAIL: elf/ifuncmain1pic
> FAIL: elf/ifuncmain1pie
> FAIL: elf/ifuncmain1staticpic
> FAIL: elf/ifuncmain1staticpie
> FAIL: elf/ifuncmain1vis
> FAIL: elf/ifuncmain1vispic
> FAIL: elf/ifuncmain1vispie
> FAIL: elf/ifuncmain3
> FAIL: elf/ifuncmain4
> FAIL: elf/ifuncmain5staticpic
> FAIL: elf/ifuncmain7
> FAIL: elf/ifuncmain7pic
> FAIL: elf/ifuncmain7pie
>
> Note that Binutils test suite is far from complete.  For example, the
> ifunc handling for LoongArch target in master branch (with or w/o this
> patch) can pass all ld tests, but it just blows up with a simple test
> case:
>
> $ cat c.s
> .global ifunc
> .type ifunc, @gnu_indirect_function
> .set ifunc, resolver
>
> resolver:
>    la.local $a0, impl
>    jr $ra
>
> impl:
>    li.w $a0, 42
>    jr $ra
>
> .data
> .global x
> .type x, @object
> x:
>    .dword ifunc
>
> $ cc c.s -shared
> collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped
> compilation terminated.
>
> So I think you'll at least need to build kernel/glibc/gcc using a ld
> with your patches to make sure it works correctly.

This is a bug, will be triggered:
1. a pointer point to a global ifunc,
2. compiling into a shared dynamic library.

We will fix and test this issue soon.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-18 10:06 ` [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types WANG Xuerui
  2022-07-18 11:33   ` Xi Ruoyao
@ 2022-07-19  7:32   ` liuzhensong
  2022-07-20  2:42   ` liuzhensong
  2 siblings, 0 replies; 24+ messages in thread
From: liuzhensong @ 2022-07-19  7:32 UTC (permalink / raw)
  To: WANG Xuerui, binutils; +Cc: xuchenghua, mengqinggang, Xi Ruoyao, Fangrui Song


在 2022/7/18 下午6:06, WANG Xuerui 写道:
> (Adding Ruoyao and MaskRay to CC, who might be interested in this 
> development as well, as it concerns the linker implementation.)
>
>
> On 2022/7/18 16:43, liuzhensong wrote:
>
>> This is the v1 version of patches to support new relocs for LoongArch.
>>
>> The new reloc types docnments are on:
>> https://github.com/loongson/LoongArch-Documentation/pull/57/files
>>
>> The testsuite status:
>>
>>                  === binutils Summary ===
>> # of expected passes            241
>> # of unsupported tests          6
>>
>>                  === gas Summary ===
>> # of expected passes            270
>> # of unsupported tests          7
>>
>>                  === ld Summary ===
>> # of expected passes            1457
>> # of expected failures          11
>> # of untested testcases         1
>> # of unsupported tests          154
>>
> I assume the content above are the "cover letter".
>
> BTW: you can generate a proper patch series with `git format-patch -vN 
> --cover-letter <base>`; I think the mails in this series were manually 
> edited by you since the "v1" is wrongly placed (it's usually "[PATCH 
> vN NN/NN]").
>
>>    Add new reloc types support, the new relocate type
>>    definition depends which operation needs of linker.
> "Define new reloc types according to linker needs" could be enough.
>>
>>
>> ---
>>   bfd/bfd-in2.h           |   36 ++
>>   bfd/elfnn-loongarch.c   | 1194 ++++++++++++++++++++++------------
>>   bfd/elfxx-loongarch.c   | 1354 +++++++++++++++++++++++++++++----------
>>   bfd/elfxx-loongarch.h   |    4 +
>>   bfd/libbfd.h            |   36 ++
>>   bfd/reloc.c             |   79 +++
>>   include/elf/loongarch.h |  142 +++-
>>   7 files changed, 2095 insertions(+), 750 deletions(-)
>>
>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>> index 4e1182e93d4..a71b3e82057 100644
>> --- a/bfd/bfd-in2.h
>> +++ b/bfd/bfd-in2.h
>> @@ -6274,6 +6274,42 @@ assembler and not (currently) written to any 
>> object files.  */
>>     BFD_RELOC_LARCH_SUB24,
>>     BFD_RELOC_LARCH_SUB32,
>>     BFD_RELOC_LARCH_SUB64,
>> +  BFD_RELOC_LARCH_B16,
>> +  BFD_RELOC_LARCH_B21,
>> +  BFD_RELOC_LARCH_B26,
>> +  BFD_RELOC_LARCH_ABS_HI20,
>> +  BFD_RELOC_LARCH_ABS_LO12,
>> +  BFD_RELOC_LARCH_ABS64_LO20,
>> +  BFD_RELOC_LARCH_ABS64_HI12,
>> +  BFD_RELOC_LARCH_PCALA_HI20,
>> +  BFD_RELOC_LARCH_PCALA_LO12,
>> +  BFD_RELOC_LARCH_PCALA64_LO20,
>> +  BFD_RELOC_LARCH_PCALA64_HI12,
>> +  BFD_RELOC_LARCH_GOT_PC_HI20,
>> +  BFD_RELOC_LARCH_GOT_PC_LO12,
>> +  BFD_RELOC_LARCH_GOT64_PC_LO20,
>> +  BFD_RELOC_LARCH_GOT64_PC_HI12,
>> +  BFD_RELOC_LARCH_GOT64_HI20,
>> +  BFD_RELOC_LARCH_GOT64_LO12,
>> +  BFD_RELOC_LARCH_GOT64_LO20,
>> +  BFD_RELOC_LARCH_GOT64_HI12,
>> +  BFD_RELOC_LARCH_TLS_LE_HI20,
>> +  BFD_RELOC_LARCH_TLS_LE_LO12,
>> +  BFD_RELOC_LARCH_TLS_LE64_LO20,
>> +  BFD_RELOC_LARCH_TLS_LE64_HI12,
>> +  BFD_RELOC_LARCH_TLS_IE_PC_HI20,
>> +  BFD_RELOC_LARCH_TLS_IE_PC_LO12,
>> +  BFD_RELOC_LARCH_TLS_IE64_PC_LO20,
>> +  BFD_RELOC_LARCH_TLS_IE64_PC_HI12,
>> +  BFD_RELOC_LARCH_TLS_IE64_HI20,
>> +  BFD_RELOC_LARCH_TLS_IE64_LO12,
>> +  BFD_RELOC_LARCH_TLS_IE64_LO20,
>> +  BFD_RELOC_LARCH_TLS_IE64_HI12,
>> +  BFD_RELOC_LARCH_TLS_LD_PC_HI20,
>> +  BFD_RELOC_LARCH_TLS_LD64_HI20,
>> +  BFD_RELOC_LARCH_TLS_GD_PC_HI20,
>> +  BFD_RELOC_LARCH_TLS_GD64_HI20,
>
> I think I've voiced my concerns over the naming of these ops multiple 
> times already; the primary comment ([1]; in English) was posted back 
> in May but no one in your team responded.
>
> Reproducing the content (and adjusting a little) here:
>
>
> Overall in a good direction (and IMHO the direction everyone should 
> have taken in the first place), thanks! A few suggestions though:
>
> Some of the names can be a bit hard to understand, for example 
> ABS_LO12, ABS_HI20, ABS64_LO20 and ABS64_HI12; these are ambiguous on 
> a first look, do you use the latter two instead of the former for 
> 64-bit absolute relocs? (The answer is "no"; you use all 4. The latter 
> two actually express the higher 32-bit half.)
>
> After having trained your intuition to work in "the Loongson way", 
> you'll then have to mentally add the "lower/higher half" and "width" 
> together to get a picture of the bit-field being expressed. It could 
> be better to somehow directly show the 0(LO)/12/32/52 inside those names.
>
> Plus, currently it's implied that a particular relocation type is 
> somehow bound to a specific instruction, that's being used by the 
> reference implementation (binutils) for the type today. This is being 
> a bit too specific, and could change, as future instructions emerge 
> with similar or identical format. (BTW no one really understand what 
> "ALA" means in "PCALA"; the insn is named "PCALAU12I", the "U12I" part 
> is similar to "LU12I.W" thus understandable, and PC is obvious, but no 
> explanation for "ALA" exists anywhere). It's better to express the 
> "destination" not in terms of instruction names or vague 
> "LO12/HI20/LO20/HI12" specifiers, but in terms of actual *instruction 
> word slots* being filled. This way it's immediately obvious for anyone 
> what place in the insn word the reloc is going to write to, without 
> having to dig into actual linker code. However, you don't officially 
> have a naming scheme for these, so I guess that's why you have to 
> invent names (and be different with others & prior work).
>
> I have drafted my scheme back in November 2021, which I posted at [2] 
> a while ago; the approach is extremely similar (IMO there's only one 
> possible way to implement the more traditional scheme), but my version 
> has adopted the operand slot naming scheme of loongarch-opcodes ([3]; 
> the convention document is edited and posted at [4] for inclusion in 
> official LoongArch docs collection) and the more direct LO/12/32/52 
> names for bit-field offsets (width is implied by the destination 
> slot). Hope this would be useful.
>
>
> Again, I may sound like a bikeshedder, but IMO better names benefit 
> everyone in the long term. I for one definitely don't want to see all 
> four of "LO12/HI20/LO20/HI12" (they refer to the two 32-bit halves of 
> a 64-bit value, not two ways to segment one 32-bit value), nor 
> "B16/B21/B26" (which are more different than you might think).
>
> [1]: https://github.com/loongson/LoongArch-Documentation/pull/50
> [2]: 
> https://github.com/loongson/binutils-gdb/issues/134#issuecomment-1110510582
> [3]: https://github.com/loongson-community/loongarch-opcodes
> [4]: https://github.com/loongson/LoongArch-Documentation/pull/56
>
>
> FYI, I did make a list of my suggested names for these reloc types 
> ("BFD_RELOC_LARCH_" abbreviated to "B_R_L_"):
>
> Original name           Suggested name
> -------------           --------------
> B_R_L_B16               B_R_L_PCREL_SK16 *1
> B_R_L_B21               B_R_L_PCREL_SD5K16
> B_R_L_B26               B_R_L_PCREL_SD10K16
> B_R_L_ABS_LO12          B_R_L_ABS_0_SK12
> B_R_L_ABS_HI20          B_R_L_ABS_12_SJ20
> B_R_L_ABS64_LO20        B_R_L_ABS_32_SJ20
> B_R_L_ABS64_HI12        B_R_L_ABS_52_SK12
> B_R_L_PCALA_LO12        B_R_L_PCALA_0_SK12 *2
> B_R_L_PCALA_HI20        B_R_L_PCALA_12_SJ20
> B_R_L_PCALA64_LO20      B_R_L_PCALA_32_SJ20 *3
> B_R_L_PCALA64_HI12      B_R_L_PCALA_52_SK12
> B_R_L_GOT_PC_LO12       B_R_L_GOT_PCALA_0_SK12 *4
> B_R_L_GOT_PC_HI20       B_R_L_GOT_PCALA_12_SJ20
> B_R_L_GOT64_PC_LO20     B_R_L_GOT_PCALA_32_SJ20
> B_R_L_GOT64_PC_HI12     B_R_L_GOT_PCALA_52_SK12
> B_R_L_GOT64_LO12        B_R_L_GOT_ABS_0_SK12 *5
> B_R_L_GOT64_HI20        B_R_L_GOT_ABS_12_SJ20
> B_R_L_GOT64_LO20        B_R_L_GOT_ABS_32_SJ20
> B_R_L_GOT64_HI12        B_R_L_GOT_ABS_52_SK12
> B_R_L_TLS_LE_LO12       B_R_L_TLS_LE_ABS_0_SK12
> B_R_L_TLS_LE_HI20       B_R_L_TLS_LE_ABS_12_SJ20
> B_R_L_TLS_LE64_LO20     B_R_L_TLS_LE_ABS_32_SJ20
> B_R_L_TLS_LE64_HI12     B_R_L_TLS_LE_ABS_52_SK12
> B_R_L_TLS_IE_PC_LO12    B_R_L_TLS_IE_PCALA_0_SK12
> B_R_L_TLS_IE_PC_HI20    B_R_L_TLS_IE_PCALA_12_SJ20
> B_R_L_TLS_IE64_PC_LO20  B_R_L_TLS_IE_PCALA_32_SJ20
> B_R_L_TLS_IE64_PC_HI12  B_R_L_TLS_IE_PCALA_52_SK12
> B_R_L_TLS_IE64_LO12     B_R_L_TLS_IE_ABS_0_SK12
> B_R_L_TLS_IE64_HI20     B_R_L_TLS_IE_ABS_12_SJ20
> B_R_L_TLS_IE64_LO20     B_R_L_TLS_IE_ABS_32_SJ20
> B_R_L_TLS_IE64_HI12     B_R_L_TLS_IE_ABS_52_SK12
> B_R_L_TLS_LD_PC_HI20    B_R_L_TLS_LD_PCALA_12_SJ20 *6
> B_R_L_TLS_LD64_HI20     B_R_L_TLS_LD_ABS_12_SJ20
> B_R_L_TLS_GD_PC_HI20    B_R_L_TLS_GD_PCALA_12_SJ20
> B_R_L_TLS_GD64_HI20     B_R_L_TLS_GD_ABS_12_SJ20
>
> *1 PCREL is explicitly called out. As you can see, every reloc type 
> looks like "<purpose>_<starting bit position>_<destination slot>".
> *2 I've reordered the types so that in each group of 4 reloc types 
> it's always from LSB to MSB. And while I don't know what "PCALA" 
> means, I've kept them all, and distinct from "PCREL" because the jumps 
> and PCADDU12I don't clear the lowest 12 bits of destination, thus 
> immediates for use with PCALAU12I needs to be differentiated.
> *3 With the starting bit position explicit called out, no "64" 
> distinction needs to be made.
> *4 This (and others) actually uses the PCALAU12I, so should be named 
> accordingly.
> *5 This (and others) seems like an absolute reloc (it uses the same 
> LU12I.W + xxx + LU32I.D + LU52I.D sequence), so ABS is added to name.
> *6 I can't immediately make sense of the last 4 reloc types, but I've 
> renamed these too. I would have to dig deeper for understanding the 
> expected use case.
>
> And I hope with this proposal, the (bikeshedding) discussion could be 
> well-founded and constructive.
>
>> +  BFD_RELOC_LARCH_RELAX,
> I see this is just being reserved but without any actual behavior 
> specified. Is it better to just leave it out for now?
>
> <snip>
>
>>     /* Processor specific flags for the ELF header e_flags field.  */
>> @@ -102,9 +238,9 @@ END_RELOC_NUMBERS (R_LARCH_count)
>>   #define EF_LOONGARCH_ABI_ILP32_SINGLE_FLOAT    0x6
>>   #define EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT    0x7
>>   -#define EF_LOONGARCH_ABI_MASK                0x7
>> -#define EF_LOONGARCH_ABI_ILP32_MASK            0x4
>> -#define EF_LOONGARCH_ABI_FLOAT_MASK            0x3
>> +#define EF_LOONGARCH_ABI_MASK            0x7
>> +#define EF_LOONGARCH_ABI_ILP32_MASK        0x4
>> +#define EF_LOONGARCH_ABI_FLOAT_MASK        0x3
>>   #define EF_LOONGARCH_ABI_SOFT_FLOAT_MASK    0x1
>>   #define EF_LOONGARCH_ABI_SINGLE_FLOAT_MASK    0x2
>>   #define EF_LOONGARCH_ABI_DOUBLE_FLOAT_MASK    0x3
> This hunk looks like pure cosmetic change, could this be split out 
> (and get committed very quickly unlike the other major changes)?
This may be caused by hand error, the next commit will revert.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-18 12:11     ` WANG Xuerui
  2022-07-18 12:18       ` WANG Xuerui
  2022-07-19  3:57       ` Fangrui Song
@ 2022-07-20  2:07       ` liuzhensong
  2022-07-20  4:03         ` WANG Xuerui
  2 siblings, 1 reply; 24+ messages in thread
From: liuzhensong @ 2022-07-20  2:07 UTC (permalink / raw)
  To: WANG Xuerui
  Cc: Xi Ruoyao, binutils, xuchenghua, mengqinggang, Fangrui Song, huangpei




> -----原始邮件-----
> 发件人: "WANG Xuerui" <i.swmail@xen0n.name>
> 发送时间: 2022-07-18 20:11:27 (星期一)
> 收件人: "Xi Ruoyao" <xry111@xry111.site>, "WANG Xuerui" <i.swmail@xen0n.name>, liuzhensong <liuzhensong@loongson.cn>, binutils@sourceware.org
> 抄送: xuchenghua@loongson.cn, mengqinggang@loongson.cn, "Fangrui Song" <maskray@google.com>
> 主题: Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
> 
> On 2022/7/18 19:33, Xi Ruoyao wrote:
> > On Mon, 2022-07-18 at 18:06 +0800, WANG Xuerui wrote:
> >> (Adding Ruoyao and MaskRay to CC, who might be interested in this
> >> development as well, as it concerns the linker implementation.)
> > I've already subscribed binutils@sourceware.org in order not to be
> > passed by.
> >
> >> I think I've voiced my concerns over the naming of these ops multiple
> >> times already; the primary comment ([1]; in English) was posted back in
> >> May but no one in your team responded.
> >>
> >> Reproducing the content (and adjusting a little) here:
> >>
> >>
> >> Overall in a good direction (and IMHO the direction everyone should have
> >> taken in the first place), thanks!
> >>
> > Yes, we've been paying additional costs using those "stack based
> > relocation".  I'd like to know why they were proposed in first place?
> > (Not accusing anyone, just my curiosity: AFAIK no other targets ever
> > used such a stack for relocation.)
> As previously pointed out on this list, rx and rl78 both use stack-based 
> relocs. (Both come from Renesas, so I do think it's delibrate design 
> decision, but of course the original Renesas justification is most 
> probably buried in history.) I explained this in 
> https://github.com/loongson/binutils-gdb/issues/134 before.
> >
> > /* snip */
> >
> >
> >> FYI, I did make a list of my suggested names for these reloc types
> >> ("BFD_RELOC_LARCH_" abbreviated to "B_R_L_"):
> >>
> >> Original name           Suggested name
> >> -------------           --------------
> >> B_R_L_B16               B_R_L_PCREL_SK16 *1
> >> B_R_L_B21               B_R_L_PCREL_SD5K16
> >> B_R_L_B26               B_R_L_PCREL_SD10K16
> >> B_R_L_ABS_LO12          B_R_L_ABS_0_SK12
> >> B_R_L_ABS_HI20          B_R_L_ABS_12_SJ20
> >> B_R_L_ABS64_LO20        B_R_L_ABS_32_SJ20
> >> B_R_L_ABS64_HI12        B_R_L_ABS_52_SK12
> >> B_R_L_PCALA_LO12        B_R_L_PCALA_0_SK12 *2
> >> B_R_L_PCALA_HI20        B_R_L_PCALA_12_SJ20
> >> B_R_L_PCALA64_LO20      B_R_L_PCALA_32_SJ20 *3
> >> B_R_L_PCALA64_HI12      B_R_L_PCALA_52_SK12
> >> B_R_L_GOT_PC_LO12       B_R_L_GOT_PCALA_0_SK12 *4
> >> B_R_L_GOT_PC_HI20       B_R_L_GOT_PCALA_12_SJ20
> >> B_R_L_GOT64_PC_LO20     B_R_L_GOT_PCALA_32_SJ20
> >> B_R_L_GOT64_PC_HI12     B_R_L_GOT_PCALA_52_SK12
> >> B_R_L_GOT64_LO12        B_R_L_GOT_ABS_0_SK12 *5
> >> B_R_L_GOT64_HI20        B_R_L_GOT_ABS_12_SJ20
> >> B_R_L_GOT64_LO20        B_R_L_GOT_ABS_32_SJ20
> >> B_R_L_GOT64_HI12        B_R_L_GOT_ABS_52_SK12
> >> B_R_L_TLS_LE_LO12       B_R_L_TLS_LE_ABS_0_SK12
> >> B_R_L_TLS_LE_HI20       B_R_L_TLS_LE_ABS_12_SJ20
> >> B_R_L_TLS_LE64_LO20     B_R_L_TLS_LE_ABS_32_SJ20
> >> B_R_L_TLS_LE64_HI12     B_R_L_TLS_LE_ABS_52_SK12
> >> B_R_L_TLS_IE_PC_LO12    B_R_L_TLS_IE_PCALA_0_SK12
> >> B_R_L_TLS_IE_PC_HI20    B_R_L_TLS_IE_PCALA_12_SJ20
> >> B_R_L_TLS_IE64_PC_LO20  B_R_L_TLS_IE_PCALA_32_SJ20
> >> B_R_L_TLS_IE64_PC_HI12  B_R_L_TLS_IE_PCALA_52_SK12
> >> B_R_L_TLS_IE64_LO12     B_R_L_TLS_IE_ABS_0_SK12
> >> B_R_L_TLS_IE64_HI20     B_R_L_TLS_IE_ABS_12_SJ20
> >> B_R_L_TLS_IE64_LO20     B_R_L_TLS_IE_ABS_32_SJ20
> >> B_R_L_TLS_IE64_HI12     B_R_L_TLS_IE_ABS_52_SK12
> >> B_R_L_TLS_LD_PC_HI20    B_R_L_TLS_LD_PCALA_12_SJ20 *6
> >> B_R_L_TLS_LD64_HI20     B_R_L_TLS_LD_ABS_12_SJ20
> >> B_R_L_TLS_GD_PC_HI20    B_R_L_TLS_GD_PCALA_12_SJ20
> >> B_R_L_TLS_GD64_HI20     B_R_L_TLS_GD_ABS_12_SJ20
> > It's overall better, but those "J, K" etc are cryptic IMHO.  And for
> > "B_R_L_B16" I think "B_R_L_PCREL_SK16" fails to express that the offset
> > should be shifted right by 2, so I'd keep B_R_L_B16 (and similarly,
> > B_R_L_B21 and B_R_L_B26) like the PCALA case.
> >
> The slot names come from 
> https://github.com/loongson/LoongArch-Documentation/pull/56 (to 
> non-Chinese speakers: English translation still TODO, but hopefully at 
> least the ABNF and the few tables should be intelligible even without 
> translation).
> 
> As for the PCREL and implicit shifts, maybe a planned extension of the 
> slot syntax could help. I plan to submit an Assembly Language Convention 
> after the Instruction Format Convention gets reviewed and merged, and 
> with this new convention such an extension is necessary anyway for 
> accommodating the current assembly syntax as described by the ISA 
> manual, able to express the <<2's and +1's for the PC-manipulating and 
> ALSL insns.
> 
> For example, let's say the extension works like this: ordinary slot 
> syntax, plus "p", plus an postprocess operator, with "s\d+" for "imm 
> slot = assembly operand >> N", and "p\d+" for "imm slot = assembly 
> operand + N". Then we could say "B_R_L_PCREL_SK16PS2" and have all the 
> niceties. (In an ideal world, the LoongArch opcodes implementation 
> should be modified to use this convention too, so for example it will be 
> something like "DJSk16ps2" for JIRL, "JDSk16ps2" for BLT (notice the 
> reversed operand order) and "DJKUa2pp1" for ALSL insns.

Some relocation name changes make sense. But, how to name a name is a 
matter of personal aesthetics, and it is difficult to satisfy everyone. 
Does the name of the relocation matter? should we pay more attention to 
the specific implementation?  Remove useless and add needed?


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-18 10:06 ` [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types WANG Xuerui
  2022-07-18 11:33   ` Xi Ruoyao
  2022-07-19  7:32   ` liuzhensong
@ 2022-07-20  2:42   ` liuzhensong
  2 siblings, 0 replies; 24+ messages in thread
From: liuzhensong @ 2022-07-20  2:42 UTC (permalink / raw)
  To: WANG Xuerui, binutils; +Cc: xuchenghua, mengqinggang, Xi Ruoyao, Fangrui Song


在 2022/7/18 下午6:06, WANG Xuerui 写道:
> (Adding Ruoyao and MaskRay to CC, who might be interested in this 
> development as well, as it concerns the linker implementation.)
>
>
> On 2022/7/18 16:43, liuzhensong wrote:
>
>> This is the v1 version of patches to support new relocs for LoongArch.
>>
>> The new reloc types docnments are on:
>> https://github.com/loongson/LoongArch-Documentation/pull/57/files
>>
>> The testsuite status:
>>
>>                  === binutils Summary ===
>> # of expected passes            241
>> # of unsupported tests          6
>>
>>                  === gas Summary ===
>> # of expected passes            270
>> # of unsupported tests          7
>>
>>                  === ld Summary ===
>> # of expected passes            1457
>> # of expected failures          11
>> # of untested testcases         1
>> # of unsupported tests          154
>>
> I assume the content above are the "cover letter".
>
> BTW: you can generate a proper patch series with `git format-patch -vN 
> --cover-letter <base>`; I think the mails in this series were manually 
> edited by you since the "v1" is wrongly placed (it's usually "[PATCH 
> vN NN/NN]").
>
>>    Add new reloc types support, the new relocate type
>>    definition depends which operation needs of linker.
> "Define new reloc types according to linker needs" could be enough.
>>
>>
>> ---
>>   bfd/bfd-in2.h           |   36 ++
>>   bfd/elfnn-loongarch.c   | 1194 ++++++++++++++++++++++------------
>>   bfd/elfxx-loongarch.c   | 1354 +++++++++++++++++++++++++++++----------
>>   bfd/elfxx-loongarch.h   |    4 +
>>   bfd/libbfd.h            |   36 ++
>>   bfd/reloc.c             |   79 +++
>>   include/elf/loongarch.h |  142 +++-
>>   7 files changed, 2095 insertions(+), 750 deletions(-)
>>
>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>> index 4e1182e93d4..a71b3e82057 100644
>> --- a/bfd/bfd-in2.h
>> +++ b/bfd/bfd-in2.h
>> @@ -6274,6 +6274,42 @@ assembler and not (currently) written to any 
>> object files.  */
>>     BFD_RELOC_LARCH_SUB24,
>>     BFD_RELOC_LARCH_SUB32,
>>     BFD_RELOC_LARCH_SUB64,
>> +  BFD_RELOC_LARCH_B16,
>> +  BFD_RELOC_LARCH_B21,
>> +  BFD_RELOC_LARCH_B26,
>> +  BFD_RELOC_LARCH_ABS_HI20,
>> +  BFD_RELOC_LARCH_ABS_LO12,
>> +  BFD_RELOC_LARCH_ABS64_LO20,
>> +  BFD_RELOC_LARCH_ABS64_HI12,
>> +  BFD_RELOC_LARCH_PCALA_HI20,
>> +  BFD_RELOC_LARCH_PCALA_LO12,
>> +  BFD_RELOC_LARCH_PCALA64_LO20,
>> +  BFD_RELOC_LARCH_PCALA64_HI12,
>> +  BFD_RELOC_LARCH_GOT_PC_HI20,
>> +  BFD_RELOC_LARCH_GOT_PC_LO12,
>> +  BFD_RELOC_LARCH_GOT64_PC_LO20,
>> +  BFD_RELOC_LARCH_GOT64_PC_HI12,
>> +  BFD_RELOC_LARCH_GOT64_HI20,
>> +  BFD_RELOC_LARCH_GOT64_LO12,
>> +  BFD_RELOC_LARCH_GOT64_LO20,
>> +  BFD_RELOC_LARCH_GOT64_HI12,
>> +  BFD_RELOC_LARCH_TLS_LE_HI20,
>> +  BFD_RELOC_LARCH_TLS_LE_LO12,
>> +  BFD_RELOC_LARCH_TLS_LE64_LO20,
>> +  BFD_RELOC_LARCH_TLS_LE64_HI12,
>> +  BFD_RELOC_LARCH_TLS_IE_PC_HI20,
>> +  BFD_RELOC_LARCH_TLS_IE_PC_LO12,
>> +  BFD_RELOC_LARCH_TLS_IE64_PC_LO20,
>> +  BFD_RELOC_LARCH_TLS_IE64_PC_HI12,
>> +  BFD_RELOC_LARCH_TLS_IE64_HI20,
>> +  BFD_RELOC_LARCH_TLS_IE64_LO12,
>> +  BFD_RELOC_LARCH_TLS_IE64_LO20,
>> +  BFD_RELOC_LARCH_TLS_IE64_HI12,
>> +  BFD_RELOC_LARCH_TLS_LD_PC_HI20,
>> +  BFD_RELOC_LARCH_TLS_LD64_HI20,
>> +  BFD_RELOC_LARCH_TLS_GD_PC_HI20,
>> +  BFD_RELOC_LARCH_TLS_GD64_HI20,
>
> I think I've voiced my concerns over the naming of these ops multiple 
> times already; the primary comment ([1]; in English) was posted back 
> in May but no one in your team responded.
>
> Reproducing the content (and adjusting a little) here:
>
>
> Overall in a good direction (and IMHO the direction everyone should 
> have taken in the first place), thanks! A few suggestions though:
>
> Some of the names can be a bit hard to understand, for example 
> ABS_LO12, ABS_HI20, ABS64_LO20 and ABS64_HI12; these are ambiguous on 
> a first look, do you use the latter two instead of the former for 
> 64-bit absolute relocs? (The answer is "no"; you use all 4. The latter 
> two actually express the higher 32-bit half.)
>
> After having trained your intuition to work in "the Loongson way", 
> you'll then have to mentally add the "lower/higher half" and "width" 
> together to get a picture of the bit-field being expressed. It could 
> be better to somehow directly show the 0(LO)/12/32/52 inside those names.
>
> Plus, currently it's implied that a particular relocation type is 
> somehow bound to a specific instruction, that's being used by the 
> reference implementation (binutils) for the type today. This is being 
> a bit too specific, and could change, as future instructions emerge 
> with similar or identical format. (BTW no one really understand what 
> "ALA" means in "PCALA"; the insn is named "PCALAU12I", the "U12I" part 
> is similar to "LU12I.W" thus understandable, and PC is obvious, but no 
> explanation for "ALA" exists anywhere). It's better to express the 
> "destination" not in terms of instruction names or vague 
> "LO12/HI20/LO20/HI12" specifiers, but in terms of actual *instruction 
> word slots* being filled. This way it's immediately obvious for anyone 
> what place in the insn word the reloc is going to write to, without 
> having to dig into actual linker code. However, you don't officially 
> have a naming scheme for these, so I guess that's why you have to 
> invent names (and be different with others & prior work).
>
> I have drafted my scheme back in November 2021, which I posted at [2] 
> a while ago; the approach is extremely similar (IMO there's only one 
> possible way to implement the more traditional scheme), but my version 
> has adopted the operand slot naming scheme of loongarch-opcodes ([3]; 
> the convention document is edited and posted at [4] for inclusion in 
> official LoongArch docs collection) and the more direct LO/12/32/52 
> names for bit-field offsets (width is implied by the destination 
> slot). Hope this would be useful.
>
>
> Again, I may sound like a bikeshedder, but IMO better names benefit 
> everyone in the long term. I for one definitely don't want to see all 
> four of "LO12/HI20/LO20/HI12" (they refer to the two 32-bit halves of 
> a 64-bit value, not two ways to segment one 32-bit value), nor 
> "B16/B21/B26" (which are more different than you might think).
>
> [1]: https://github.com/loongson/LoongArch-Documentation/pull/50
> [2]: 
> https://github.com/loongson/binutils-gdb/issues/134#issuecomment-1110510582
> [3]: https://github.com/loongson-community/loongarch-opcodes
> [4]: https://github.com/loongson/LoongArch-Documentation/pull/56
>
>
> FYI, I did make a list of my suggested names for these reloc types 
> ("BFD_RELOC_LARCH_" abbreviated to "B_R_L_"):
>
> Original name           Suggested name
> -------------           --------------
> B_R_L_B16               B_R_L_PCREL_SK16 *1
> B_R_L_B21               B_R_L_PCREL_SD5K16
> B_R_L_B26               B_R_L_PCREL_SD10K16
> B_R_L_ABS_LO12          B_R_L_ABS_0_SK12
> B_R_L_ABS_HI20          B_R_L_ABS_12_SJ20
> B_R_L_ABS64_LO20        B_R_L_ABS_32_SJ20
> B_R_L_ABS64_HI12        B_R_L_ABS_52_SK12
> B_R_L_PCALA_LO12        B_R_L_PCALA_0_SK12 *2
> B_R_L_PCALA_HI20        B_R_L_PCALA_12_SJ20
> B_R_L_PCALA64_LO20      B_R_L_PCALA_32_SJ20 *3
> B_R_L_PCALA64_HI12      B_R_L_PCALA_52_SK12
> B_R_L_GOT_PC_LO12       B_R_L_GOT_PCALA_0_SK12 *4
> B_R_L_GOT_PC_HI20       B_R_L_GOT_PCALA_12_SJ20
> B_R_L_GOT64_PC_LO20     B_R_L_GOT_PCALA_32_SJ20
> B_R_L_GOT64_PC_HI12     B_R_L_GOT_PCALA_52_SK12
> B_R_L_GOT64_LO12        B_R_L_GOT_ABS_0_SK12 *5
> B_R_L_GOT64_HI20        B_R_L_GOT_ABS_12_SJ20
> B_R_L_GOT64_LO20        B_R_L_GOT_ABS_32_SJ20
> B_R_L_GOT64_HI12        B_R_L_GOT_ABS_52_SK12
> B_R_L_TLS_LE_LO12       B_R_L_TLS_LE_ABS_0_SK12
> B_R_L_TLS_LE_HI20       B_R_L_TLS_LE_ABS_12_SJ20
> B_R_L_TLS_LE64_LO20     B_R_L_TLS_LE_ABS_32_SJ20
> B_R_L_TLS_LE64_HI12     B_R_L_TLS_LE_ABS_52_SK12
> B_R_L_TLS_IE_PC_LO12    B_R_L_TLS_IE_PCALA_0_SK12
> B_R_L_TLS_IE_PC_HI20    B_R_L_TLS_IE_PCALA_12_SJ20
> B_R_L_TLS_IE64_PC_LO20  B_R_L_TLS_IE_PCALA_32_SJ20
> B_R_L_TLS_IE64_PC_HI12  B_R_L_TLS_IE_PCALA_52_SK12
> B_R_L_TLS_IE64_LO12     B_R_L_TLS_IE_ABS_0_SK12
> B_R_L_TLS_IE64_HI20     B_R_L_TLS_IE_ABS_12_SJ20
> B_R_L_TLS_IE64_LO20     B_R_L_TLS_IE_ABS_32_SJ20
> B_R_L_TLS_IE64_HI12     B_R_L_TLS_IE_ABS_52_SK12
> B_R_L_TLS_LD_PC_HI20    B_R_L_TLS_LD_PCALA_12_SJ20 *6
> B_R_L_TLS_LD64_HI20     B_R_L_TLS_LD_ABS_12_SJ20
> B_R_L_TLS_GD_PC_HI20    B_R_L_TLS_GD_PCALA_12_SJ20
> B_R_L_TLS_GD64_HI20     B_R_L_TLS_GD_ABS_12_SJ20
>
> *1 PCREL is explicitly called out. As you can see, every reloc type 
> looks like "<purpose>_<starting bit position>_<destination slot>".
> *2 I've reordered the types so that in each group of 4 reloc types 
> it's always from LSB to MSB. And while I don't know what "PCALA" 
> means, I've kept them all, and distinct from "PCREL" because the jumps 
> and PCADDU12I don't clear the lowest 12 bits of destination, thus 
> immediates for use with PCALAU12I needs to be differentiated.
> *3 With the starting bit position explicit called out, no "64" 
> distinction needs to be made.
> *4 This (and others) actually uses the PCALAU12I, so should be named 
> accordingly.
> *5 This (and others) seems like an absolute reloc (it uses the same 
> LU12I.W + xxx + LU32I.D + LU52I.D sequence), so ABS is added to name.
> *6 I can't immediately make sense of the last 4 reloc types, but I've 
> renamed these too. I would have to dig deeper for understanding the 
> expected use case.
>
> And I hope with this proposal, the (bikeshedding) discussion could be 
> well-founded and constructive.
>
>> +  BFD_RELOC_LARCH_RELAX,
> I see this is just being reserved but without any actual behavior 
> specified. Is it better to just leave it out for now?

This relocation is expected to do some optimizations, do or not won't 
affect correctness. The linker has implemented some specific 
instructions, but the assembler still has some support that has not been 
completed. If it is deleted, the current version linker can not to link 
next version object (maybe soon to be patched).

>
> <snip>
>
>>     /* Processor specific flags for the ELF header e_flags field.  */
>> @@ -102,9 +238,9 @@ END_RELOC_NUMBERS (R_LARCH_count)
>>   #define EF_LOONGARCH_ABI_ILP32_SINGLE_FLOAT    0x6
>>   #define EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT    0x7
>>   -#define EF_LOONGARCH_ABI_MASK                0x7
>> -#define EF_LOONGARCH_ABI_ILP32_MASK            0x4
>> -#define EF_LOONGARCH_ABI_FLOAT_MASK            0x3
>> +#define EF_LOONGARCH_ABI_MASK            0x7
>> +#define EF_LOONGARCH_ABI_ILP32_MASK        0x4
>> +#define EF_LOONGARCH_ABI_FLOAT_MASK        0x3
>>   #define EF_LOONGARCH_ABI_SOFT_FLOAT_MASK    0x1
>>   #define EF_LOONGARCH_ABI_SINGLE_FLOAT_MASK    0x2
>>   #define EF_LOONGARCH_ABI_DOUBLE_FLOAT_MASK    0x3
> This hunk looks like pure cosmetic change, could this be split out 
> (and get committed very quickly unlike the other major changes)?

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-20  2:07       ` liuzhensong
@ 2022-07-20  4:03         ` WANG Xuerui
  2022-07-20  5:19           ` Xi Ruoyao
  2022-07-20 12:54           ` liuzhensong
  0 siblings, 2 replies; 24+ messages in thread
From: WANG Xuerui @ 2022-07-20  4:03 UTC (permalink / raw)
  To: liuzhensong, WANG Xuerui
  Cc: Xi Ruoyao, binutils, xuchenghua, mengqinggang, Fangrui Song, huangpei

On 2022/7/20 10:07, liuzhensong wrote:
>
> Some relocation name changes make sense. But, how to name a name is a 
> matter of personal aesthetics, and it is difficult to satisfy 
> everyone. Does the name of the relocation matter? should we pay more 
> attention to the specific implementation?  Remove useless and add needed?
>
Names do matter. You can't expect to lower maintenance costs and barrier 
to entry for newcomers with "bad" names. I showed the original names in 
the patch to some of my colleagues (with no low-level programming 
experience; they are all application developers), and they invariably 
can't get the distinction of "LO12/HI20/LO20/HI12". I then showed them 
my proposal, granted they needed a little explanation as to what things 
like "SK12" mean, but after that they can immediately get the feel of 
the relocs ("ah, it's like for this purpose, put this part of imm into 
this slot").

LoongArch is expected to remain niche, at least for the coming 3~5 
years, so you can't expect to have many people working on low-level 
nitty-gritty details like this. I personally don't think your team's 
composition is going to remain stable over the years, either; in either 
case, people come and go, so IMO there is indeed value in this 
bikeshedding. The community as a whole can work over concrete proposals 
of better naming, and I think my proposal serves as such a constructive 
starting point.

Also, if you think the current names are more appropriate, with 
objective reasons, then *please communicate* your justification and 
thought behind them. We "outsiders" actually intend to cooperate, and 
have voiced our thoughts, but we don't know what you and your team 
think. For now all we have is this "LO12/HI20/LO20/HI12" and outsiders 
can draw no conclusion other than "hmm this is going to cause 
confusion". We really need to communicate more in the open for pushing 
things forward, constructively.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-20  4:03         ` WANG Xuerui
@ 2022-07-20  5:19           ` Xi Ruoyao
  2022-07-20 12:54           ` liuzhensong
  1 sibling, 0 replies; 24+ messages in thread
From: Xi Ruoyao @ 2022-07-20  5:19 UTC (permalink / raw)
  To: WANG Xuerui, liuzhensong
  Cc: binutils, xuchenghua, mengqinggang, Fangrui Song, huangpei

On Wed, 2022-07-20 at 12:03 +0800, WANG Xuerui wrote:
> On 2022/7/20 10:07, liuzhensong wrote:
> > 
> > Some relocation name changes make sense. But, how to name a name is a 
> > matter of personal aesthetics, and it is difficult to satisfy 
> > everyone. Does the name of the relocation matter? should we pay more
> > attention to the specific implementation?  Remove useless and add needed?

A bug fix needs immediately attention, but a new feature may need more
discussion to make it easier to be used correctly.  I'm still reluctant
about "adding a whole bunch of new relocation just 3 weeks before
Binutils-2.39 release date".

> 
> Also, if you think the current names are more appropriate, with 
> objective reasons, then *please communicate* your justification and 
> thought behind them. We "outsiders" actually intend to cooperate, and 
> have voiced our thoughts, but we don't know what you and your team 
> think. For now all we have is this "LO12/HI20/LO20/HI12" and outsiders
> can draw no conclusion other than "hmm this is going to cause 
> confusion". We really need to communicate more in the open for pushing
> things forward, constructively.

About "LO12/HI20/LO20/HI12" vs "0/12/32/52", please consider: if someone
has not read LoongArch manual, he'll have no idea about what is "HI20"
and likely [mis]interpret it as "x[63:44]" instead of "x[51:32]".  But
if he has read LoongArch manual, the manual already uses
"LU12I.W/LU32I.D/LU52I.D".  So a different notion for the parts of
immediate seems a completely unnecessary deviation.

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-19  3:57       ` Fangrui Song
@ 2022-07-20  7:47         ` liuzhensong
  0 siblings, 0 replies; 24+ messages in thread
From: liuzhensong @ 2022-07-20  7:47 UTC (permalink / raw)
  To: Fangrui Song, WANG Xuerui; +Cc: Xi Ruoyao, binutils, xuchenghua, mengqinggang


在 2022/7/19 上午11:57, Fangrui Song 写道:
> On 2022-07-18, WANG Xuerui wrote:
>> On 2022/7/18 19:33, Xi Ruoyao wrote:
>>> On Mon, 2022-07-18 at 18:06 +0800, WANG Xuerui wrote:
>>>> (Adding Ruoyao and MaskRay to CC, who might be interested in this
>>>> development as well, as it concerns the linker implementation.)
>>> I've already subscribed binutils@sourceware.org in order not to be
>>> passed by.
>
> I am subscribed, too. Direct CC helps me find the discussions:)
>
>>>> I think I've voiced my concerns over the naming of these ops multiple
>>>> times already; the primary comment ([1]; in English) was posted 
>>>> back in
>>>> May but no one in your team responded.
>>>>
>>>> Reproducing the content (and adjusting a little) here:
>>>>
>>>>
>>>> Overall in a good direction (and IMHO the direction everyone should 
>>>> have
>>>> taken in the first place), thanks!
>>>>
>>> Yes, we've been paying additional costs using those "stack based
>>> relocation".  I'd like to know why they were proposed in first place?
>>> (Not accusing anyone, just my curiosity: AFAIK no other targets ever
>>> used such a stack for relocation.)
>> As previously pointed out on this list, rx and rl78 both use 
>> stack-based relocs. (Both come from Renesas, so I do think it's 
>> delibrate design decision, but of course the original Renesas 
>> justification is most probably buried in history.) I explained this 
>> in https://github.com/loongson/binutils-gdb/issues/134 before.
>
> Stack machines aren't really suitable for ELF relocations.
> Each relocation takes sizeof(Elf64_Rela) = 24 byte, higher than older
> object file formats.
>
> ELF32 allows 256 relocation types. There aren't too many to waste.
>
>>>
>>> /* snip */
>>>
>>>
>>>> FYI, I did make a list of my suggested names for these reloc types
>>>> ("BFD_RELOC_LARCH_" abbreviated to "B_R_L_"):
>>>>
>>>> Original name           Suggested name
>>>> -------------           --------------
>>>> B_R_L_B16               B_R_L_PCREL_SK16 *1
>>>> B_R_L_B21               B_R_L_PCREL_SD5K16
>>>> B_R_L_B26               B_R_L_PCREL_SD10K16
>>>> B_R_L_ABS_LO12          B_R_L_ABS_0_SK12
>>>> B_R_L_ABS_HI20          B_R_L_ABS_12_SJ20
>>>> B_R_L_ABS64_LO20        B_R_L_ABS_32_SJ20
>>>> B_R_L_ABS64_HI12        B_R_L_ABS_52_SK12
>
> aarch64 calls these G0/G1/G2/G3 while ppc calls these 
> LO/HI/HIGHER/HIGHEST.
> A name mentioning the offset and the length looks good to me, too.
> A too-long name may have problems in the default (non-wide) output of
> readelf -r.
>
>>>> B_R_L_PCALA_LO12 B_R_L_PCALA_0_SK12 *2
>>>> B_R_L_PCALA_HI20        B_R_L_PCALA_12_SJ20
>>>> B_R_L_PCALA64_LO20      B_R_L_PCALA_32_SJ20 *3
>>>> B_R_L_PCALA64_HI12      B_R_L_PCALA_52_SK12
>>>> B_R_L_GOT_PC_LO12       B_R_L_GOT_PCALA_0_SK12 *4
>>>> B_R_L_GOT_PC_HI20       B_R_L_GOT_PCALA_12_SJ20
>>>> B_R_L_GOT64_PC_LO20     B_R_L_GOT_PCALA_32_SJ20
>>>> B_R_L_GOT64_PC_HI12     B_R_L_GOT_PCALA_52_SK12
>>>> B_R_L_GOT64_LO12        B_R_L_GOT_ABS_0_SK12 *5
>>>> B_R_L_GOT64_HI20        B_R_L_GOT_ABS_12_SJ20
>>>> B_R_L_GOT64_LO20        B_R_L_GOT_ABS_32_SJ20
>>>> B_R_L_GOT64_HI12        B_R_L_GOT_ABS_52_SK12
>
>
>>>> B_R_L_TLS_LE_LO12 B_R_L_TLS_LE_ABS_0_SK12
>>>> B_R_L_TLS_LE_HI20       B_R_L_TLS_LE_ABS_12_SJ20
>>>> B_R_L_TLS_LE64_LO20     B_R_L_TLS_LE_ABS_32_SJ20
>>>> B_R_L_TLS_LE64_HI12     B_R_L_TLS_LE_ABS_52_SK12
>>>> B_R_L_TLS_IE_PC_LO12    B_R_L_TLS_IE_PCALA_0_SK12
>>>> B_R_L_TLS_IE_PC_HI20    B_R_L_TLS_IE_PCALA_12_SJ20
>>>> B_R_L_TLS_IE64_PC_LO20  B_R_L_TLS_IE_PCALA_32_SJ20
>>>> B_R_L_TLS_IE64_PC_HI12  B_R_L_TLS_IE_PCALA_52_SK12
>>>> B_R_L_TLS_IE64_LO12     B_R_L_TLS_IE_ABS_0_SK12
>>>> B_R_L_TLS_IE64_HI20     B_R_L_TLS_IE_ABS_12_SJ20
>>>> B_R_L_TLS_IE64_LO20     B_R_L_TLS_IE_ABS_32_SJ20
>>>> B_R_L_TLS_IE64_HI12     B_R_L_TLS_IE_ABS_52_SK12
>>>> B_R_L_TLS_LD_PC_HI20    B_R_L_TLS_LD_PCALA_12_SJ20 *6
>>>> B_R_L_TLS_LD64_HI20     B_R_L_TLS_LD_ABS_12_SJ20
>>>> B_R_L_TLS_GD_PC_HI20    B_R_L_TLS_GD_PCALA_12_SJ20
>>>> B_R_L_TLS_GD64_HI20     B_R_L_TLS_GD_ABS_12_SJ20
>
> aarch64 relocation types are well named. It's obvious what suppress
> overflow checking.
>
> For LO12, I expect that there are two variants: one with overflow check,
> the other without.
>
In what scenarios will no check overflow be used? Any documentation or 
examples?

>>> It's overall better, but those "J, K" etc are cryptic IMHO.  And for
>>> "B_R_L_B16" I think "B_R_L_PCREL_SK16" fails to express that the offset
>>> should be shifted right by 2, so I'd keep B_R_L_B16 (and similarly,
>>> B_R_L_B21 and B_R_L_B26) like the PCALA case.
>>>
>> The slot names come from 
>> https://github.com/loongson/LoongArch-Documentation/pull/56 (to 
>> non-Chinese speakers: English translation still TODO, but hopefully 
>> at least the ABNF and the few tables should be intelligible even 
>> without translation).
>>
>> As for the PCREL and implicit shifts, maybe a planned extension of 
>> the slot syntax could help. I plan to submit an Assembly Language 
>> Convention after the Instruction Format Convention gets reviewed and 
>> merged, and with this new convention such an extension is necessary 
>> anyway for accommodating the current assembly syntax as described by 
>> the ISA manual, able to express the <<2's and +1's for the 
>> PC-manipulating and ALSL insns.
>>
>> For example, let's say the extension works like this: ordinary slot 
>> syntax, plus "p", plus an postprocess operator, with "s\d+" for "imm 
>> slot = assembly operand >> N", and "p\d+" for "imm slot = assembly 
>> operand + N". Then we could say "B_R_L_PCREL_SK16PS2" and have all 
>> the niceties. (In an ideal world, the LoongArch opcodes 
>> implementation should be modified to use this convention too, so for 
>> example it will be something like "DJSk16ps2" for JIRL, "JDSk16ps2" 
>> for BLT (notice the reversed operand order) and "DJKUa2pp1" for ALSL 
>> insns.
>>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types.
  2022-07-20  4:03         ` WANG Xuerui
  2022-07-20  5:19           ` Xi Ruoyao
@ 2022-07-20 12:54           ` liuzhensong
  1 sibling, 0 replies; 24+ messages in thread
From: liuzhensong @ 2022-07-20 12:54 UTC (permalink / raw)
  To: WANG Xuerui
  Cc: Xi Ruoyao, binutils, xuchenghua, mengqinggang, Fangrui Song, huangpei


在 2022/7/20 下午12:03, WANG Xuerui 写道:
> On 2022/7/20 10:07, liuzhensong wrote:
>>
>> Some relocation name changes make sense. But, how to name a name is a 
>> matter of personal aesthetics, and it is difficult to satisfy 
>> everyone. Does the name of the relocation matter? should we pay more 
>> attention to the specific implementation?  Remove useless and add 
>> needed?
>>
> Names do matter. You can't expect to lower maintenance costs and 
> barrier to entry for newcomers with "bad" names. I showed the original 
> names in the patch to some of my colleagues (with no low-level 
> programming experience; they are all application developers), and they 
> invariably can't get the distinction of "LO12/HI20/LO20/HI12". I then 
> showed them my proposal, granted they needed a little explanation as 
> to what things like "SK12" mean, but after that they can immediately 
> get the feel of the relocs ("ah, it's like for this purpose, put this 
> part of imm into this slot").
>
> LoongArch is expected to remain niche, at least for the coming 3~5 
> years, so you can't expect to have many people working on low-level 
> nitty-gritty details like this. I personally don't think your team's 
> composition is going to remain stable over the years, either; in 
> either case, people come and go, so IMO there is indeed value in this 
> bikeshedding. The community as a whole can work over concrete 
> proposals of better naming, and I think my proposal serves as such a 
> constructive starting point.
>
> Also, if you think the current names are more appropriate, with 
> objective reasons, then *please communicate* your justification and 
> thought behind them. We "outsiders" actually intend to cooperate, and 
> have voiced our thoughts, but we don't know what you and your team 
> think. For now all we have is this "LO12/HI20/LO20/HI12" and outsiders 
> can draw no conclusion other than "hmm this is going to cause 
> confusion". We really need to communicate more in the open for pushing 
> things forward, constructively.

Your relocation is fine, but it's a bit long and complicated and 
informative(personaly opinion). It seems unlikely to modify code just by 
relocation name, there is necessary to understand the instructions 
represented by relocation.

I made some adjustments to some relocations, then, LO12 and HI20 
implement 32-bit relocation, xxx64_LO20 and xxx64_HI12 implement high 
32bits of 64-bit relocation while low 32bits use LO12 and HI20. In my 
opinion, it is enough to know what to do by name.

LO12 [11:0] HI20 [31:12] 64_LO20 [51:32] 64_HI12 [63:52] Changes,

1. B_R_L_GOT64_LO12          B_R_L_GOT_LO12
2. B_R_L_GOT64_HI20          B_R_L_GOT_HI20
3. B_R_L_TLS64_IE_LO12       B_R_L_TLS_IE_LO12
4. B_R_L_TLS64_IE_HI20       B_R_L_TLS_IE_HI20
5. B_R_L_TLS64_LD_HI20       B_R_L_TLS_LD_HI20
6. B_R_L_TLS64_GD_HI20       B_R_L_TLS_GD_HI20

  

    Original name           Suggested name
    -------------           --------------
    B_R_L_B16               B_R_L_PCREL_SK16
    B_R_L_B21               B_R_L_PCREL_SD5K16
    B_R_L_B26               B_R_L_PCREL_SD10K16
    B_R_L_ABS_LO12          B_R_L_ABS_0_SK12
    B_R_L_ABS_HI20          B_R_L_ABS_12_SJ20
    B_R_L_ABS64_LO20        B_R_L_ABS_32_SJ20
    B_R_L_ABS64_HI12        B_R_L_ABS_52_SK12
    B_R_L_PCALA_LO12        B_R_L_PCALA_0_SK12
    B_R_L_PCALA_HI20        B_R_L_PCALA_12_SJ20
    B_R_L_PCALA64_LO20      B_R_L_PCALA_32_SJ20
    B_R_L_PCALA64_HI12      B_R_L_PCALA_52_SK12
    B_R_L_GOT_PC_LO12       B_R_L_GOT_PCALA_0_SK12
    B_R_L_GOT_PC_HI20       B_R_L_GOT_PCALA_12_SJ20
    B_R_L_GOT64_PC_LO20     B_R_L_GOT_PCALA_32_SJ20
    B_R_L_GOT64_PC_HI12     B_R_L_GOT_PCALA_52_SK12
1. B_R_L_GOT_LO12          B_R_L_GOT_ABS_0_SK12
2. B_R_L_GOT_HI20          B_R_L_GOT_ABS_12_SJ20
    B_R_L_GOT64_LO20        B_R_L_GOT_ABS_32_SJ20
    B_R_L_GOT64_HI12        B_R_L_GOT_ABS_52_SK12
    B_R_L_TLS_LE_LO12       B_R_L_TLS_LE_ABS_0_SK12
    B_R_L_TLS_LE_HI20       B_R_L_TLS_LE_ABS_12_SJ20
    B_R_L_TLS_LE64_LO20     B_R_L_TLS_LE_ABS_32_SJ20
    B_R_L_TLS_LE64_HI12     B_R_L_TLS_LE_ABS_52_SK12
    B_R_L_TLS_IE_PC_LO12    B_R_L_TLS_IE_PCALA_0_SK12
    B_R_L_TLS_IE_PC_HI20    B_R_L_TLS_IE_PCALA_12_SJ20
    B_R_L_TLS_IE64_PC_LO20  B_R_L_TLS_IE_PCALA_32_SJ20
    B_R_L_TLS_IE64_PC_HI12  B_R_L_TLS_IE_PCALA_52_SK12
3. B_R_L_TLS_IE_LO12       B_R_L_TLS_IE_ABS_0_SK12
4. B_R_L_TLS_IE_HI20       B_R_L_TLS_IE_ABS_12_SJ20
    B_R_L_TLS_IE64_LO20     B_R_L_TLS_IE_ABS_32_SJ20
    B_R_L_TLS_IE64_HI12     B_R_L_TLS_IE_ABS_52_SK12
    B_R_L_TLS_LD_PC_HI20    B_R_L_TLS_LD_PCALA_12_SJ20
5. B_R_L_TLS_LD_HI20       B_R_L_TLS_LD_ABS_12_SJ20
    B_R_L_TLS_GD_PC_HI20    B_R_L_TLS_GD_PCALA_12_SJ20
6. B_R_L_TLS_GD_HI20       B_R_L_TLS_GD_ABS_12_SJ20


  


^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2022-07-20 12:54 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-18  8:43 [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types liuzhensong
2022-07-18  8:43 ` [PATCH 2/5 v1] LoongArch:opcodes: " liuzhensong
2022-07-18  8:43 ` [PATCH 3/5 v1] LoongArch: gas: " liuzhensong
2022-07-18  8:43 ` [PATCH 4/5 v1] LoongArch: Move ifunc info to rela.dyn from rela.plt liuzhensong
2022-07-18 11:45   ` Xi Ruoyao
2022-07-18 16:27   ` Xi Ruoyao
2022-07-19  7:26     ` liuzhensong
2022-07-18  8:43 ` [PATCH 5/5 v1] LoongArch: Delete R_LARCH_NONE from dynamic info liuzhensong
2022-07-18 10:06 ` [PATCH 1/5 v1] LoongArch: bfd: Add new reloc types WANG Xuerui
2022-07-18 11:33   ` Xi Ruoyao
2022-07-18 12:11     ` WANG Xuerui
2022-07-18 12:18       ` WANG Xuerui
2022-07-19  3:57       ` Fangrui Song
2022-07-20  7:47         ` liuzhensong
2022-07-20  2:07       ` liuzhensong
2022-07-20  4:03         ` WANG Xuerui
2022-07-20  5:19           ` Xi Ruoyao
2022-07-20 12:54           ` liuzhensong
2022-07-19  7:32   ` liuzhensong
2022-07-20  2:42   ` liuzhensong
2022-07-19  4:29 ` Xi Ruoyao
2022-07-19  5:40   ` Xi Ruoyao
2022-07-19  6:31     ` 刘振松
2022-07-19  6:34       ` Xi Ruoyao

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).