public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] LoongArch: Fix LD check fails.
@ 2022-03-12  7:44 liuzhensong
  0 siblings, 0 replies; only message in thread
From: liuzhensong @ 2022-03-12  7:44 UTC (permalink / raw)
  To: binutils; +Cc: liuzhensong

  Some test cases about ifunc.

  bfd/
    * elfnn-loongarch.c
    * elfxx-loongarch.h

   === ld Summary ===
  of expected passes             1430
  of expected failures           11
  of untested testcases          1
  of unsupported tests           154
---
 bfd/elfnn-loongarch.c | 341 ++++++++++++++++++++++++++++++++++--------
 bfd/elfxx-loongarch.h |   8 +
 2 files changed, 287 insertions(+), 62 deletions(-)

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index ed5d2641783..8aaf157b303 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -42,9 +42,6 @@ struct loongarch_elf_link_hash_entry
 {
   struct elf_link_hash_entry elf;
 
-  /* Track dynamic relocs copied for this symbol.  */
-  struct elf_dyn_relocs *dyn_relocs;
-
 #define GOT_UNKNOWN 0
 #define GOT_NORMAL  1
 #define GOT_TLS_GD  2
@@ -238,7 +235,6 @@ link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table,
   if (entry != NULL)
     {
       eh = (struct loongarch_elf_link_hash_entry *) entry;
-      eh->dyn_relocs = NULL;
       eh->tls_type = GOT_UNKNOWN;
     }
 
@@ -632,11 +628,21 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
 	}
 
+      /* It is referenced by a non-shared object.  */
+      if (h != NULL)
+	h->ref_regular = 1;
+
       if (h && h->type == STT_GNU_IFUNC)
 	{
 	  if (htab->elf.dynobj == NULL)
 	    htab->elf.dynobj = abfd;
 
+	  /* 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.  */
@@ -752,6 +758,24 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
 	  if (h != NULL)
 	    h->non_got_ref = 1;
+
+	  if (h != NULL
+	      && (!bfd_link_pic (info)
+		  || h->type == STT_GNU_IFUNC))
+	    {
+	      /* This reloc might not bind locally.  */
+	      h->non_got_ref = 1;
+	      h->pointer_equality_needed = 1;
+
+	      if (!h->def_regular
+		  || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
+		{
+		  /* We may need a .plt entry if the symbol is a function
+		     defined in a shared lib or is a function referenced
+		     from the code or read-only section.  */
+		  h->plt.refcount += 1;
+		}
+	    }
 	  break;
 
 	case R_LARCH_GNU_VTINHERIT:
@@ -790,7 +814,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	  /* If this is a global symbol, we count the number of
 	     relocations we need for this symbol.  */
 	  if (h != NULL)
-	    head = &((struct loongarch_elf_link_hash_entry *) h)->dyn_relocs;
+	    head = &h->dyn_relocs;
 	  else
 	    {
 	      /* Track dynamic relocs needed for local syms too.
@@ -837,7 +861,7 @@ readonly_dynrelocs (struct elf_link_hash_entry *h)
 {
   struct elf_dyn_relocs *p;
 
-  for (p = loongarch_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
+  for (p = h->dyn_relocs; p != NULL; p = p->next)
     {
       asection *s = p->sec->output_section;
 
@@ -986,13 +1010,15 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 {
   struct bfd_link_info *info;
   struct loongarch_elf_link_hash_table *htab;
-  struct loongarch_elf_link_hash_entry *eh;
   struct elf_dyn_relocs *p;
 
   if (h->root.type == bfd_link_hash_indirect)
     return true;
 
-  eh = (struct loongarch_elf_link_hash_entry *) h;
+  if (h->type == STT_GNU_IFUNC
+      && h->def_regular)
+    return true;
+
   info = (struct bfd_link_info *) inf;
   htab = loongarch_elf_hash_table (info);
   BFD_ASSERT (htab != NULL);
@@ -1041,6 +1067,18 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       gotplt->size += GOT_ENTRY_SIZE;
       relplt->size += sizeof (ElfNN_External_Rela);
 
+      /* If this symbol is not defined in a regular file, and we are
+	 not generating a shared library, then set the symbol to this
+	 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)
+	  && !h->def_regular)
+	{
+	  h->root.u.def.section = plt;
+	  h->root.u.def.value = h->plt.offset;
+	}
+
       h->needs_plt = 1;
     }
   while (0);
@@ -1056,9 +1094,20 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
       /* 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
-	  && !bfd_elf_link_record_dynamic_symbol (info, h))
-	return false;
+      if (h->dynindx == -1 && !h->forced_local)
+	{
+	  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;
+	    }
+	}
 
       s = htab->elf.sgot;
       h->got.offset = s->size;
@@ -1091,14 +1140,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   else
     h->got.offset = MINUS_ONE;
 
-  if (eh->dyn_relocs == NULL)
+  if (h->dyn_relocs == NULL)
     return true;
 
   if (SYMBOL_REFERENCES_LOCAL (info, h))
     {
       struct elf_dyn_relocs **pp;
 
-      for (pp = &eh->dyn_relocs; (p = *pp) != NULL;)
+      for (pp = &h->dyn_relocs; (p = *pp) != NULL;)
 	{
 	  p->count -= p->pc_count;
 	  p->pc_count = 0;
@@ -1112,7 +1161,7 @@ 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))
-	eh->dyn_relocs = NULL;
+	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.  */
@@ -1120,7 +1169,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 	return false;
     }
 
-  for (p = eh->dyn_relocs; p != NULL; p = p->next)
+  for (p = h->dyn_relocs; p != NULL; p = p->next)
     {
       asection *sreloc = elf_section_data (p->sec)->sreloc;
       sreloc->size += p->count * sizeof (ElfNN_External_Rela);
@@ -1129,16 +1178,60 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   return true;
 }
 
+/* Allocate space in .plt, .got and associated reloc sections for
+   ifunc dynamic relocs.  */
+
+static bool
+elfNN_loongarch_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
+     symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect)
+     -> __gxx_personality_v0(bfd_link_hash_defined)
+
+     There is no need to process bfd_link_hash_indirect symbols here
+     because we will also be presented with the concrete instance of
+     the symbol and loongarch_elf_copy_indirect_symbol () will have been
+     called to copy all relevant data from the generic to the concrete
+     symbol instance.  */
+  if (h->root.type == bfd_link_hash_indirect)
+    return true;
+
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  info = (struct bfd_link_info *) 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,
+					       &h->dyn_relocs,
+					       PLT_ENTRY_SIZE,
+					       PLT_HEADER_SIZE,
+					       GOT_ENTRY_SIZE,
+					       false);
+  return true;
+}
+
+/* Allocate space in .plt, .got and associated reloc sections for
+   ifunc dynamic relocs.  */
+
 static bool
 elfNN_loongarch_allocate_local_dynrelocs (void **slot, void *inf)
 {
   struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
 
-  if (!h->def_regular || !h->ref_regular || !h->forced_local
+  if (h->type != STT_GNU_IFUNC
+      || !h->def_regular
+      || !h->ref_regular
+      || !h->forced_local
       || h->root.type != bfd_link_hash_defined)
     abort ();
 
-  return allocate_dynrelocs (h, inf);
+  return elfNN_loongarch_allocate_ifunc_dynrelocs (h, inf);
 }
 
 /* Set DF_TEXTREL if we find any dynamic relocs that apply to
@@ -1275,6 +1368,11 @@ loongarch_elf_size_dynamic_sections (bfd *output_bfd,
   /* Allocate global sym .plt and .got entries, and space for global
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
+
+  /* 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);
+
   /* Allocate .plt and .got entries, and space for local ifunc symbols.  */
   htab_traverse (htab->loc_hash_table,
 		 (void *) elfNN_loongarch_allocate_local_dynrelocs, info);
@@ -1976,14 +2074,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	  resolved_to_const = true;
 	}
 
-      if (h && h->type == STT_GNU_IFUNC)
+      /* The ifunc without reference does not generate plt.  */
+      if (h && h->type == STT_GNU_IFUNC && h->plt.offset != MINUS_ONE)
 	{
-	  if (h->plt.offset == MINUS_ONE)
-	    info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against `%s':\n"
-				   "STT_GNU_IFUNC must have PLT stub"
-				   "\n",
-				   input_bfd, input_section,
-				   (bfd_vma) rel->r_offset, howto->name, name);
 	  defined_local = true;
 	  resolved_local = true;
 	  resolved_dynly = false;
@@ -1995,7 +2088,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
       BFD_ASSERT (resolved_local + resolved_dynly + resolved_to_const == 1);
 
-      BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1));
+      /* BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1));.  */
 
       BFD_ASSERT (!resolved_local || defined_local);
 
@@ -2026,7 +2119,31 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 				  && (input_section->flags & SEC_ALLOC));
 
 	      outrel.r_offset += sec_addr (input_section);
-	      if (resolved_dynly)
+
+	      /* A pointer point to a local ifunc symbol.  */
+	      if(h
+		 && h->type == STT_GNU_IFUNC
+		 && (h->dynindx == -1
+		     || h->forced_local
+		     || bfd_link_executable(info)))
+		{
+		  outrel.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
+		  outrel.r_addend = (h->root.u.def.value
+				     + 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;
+		  else
+		    sreloc = htab->elf.irelplt;
+		}
+	      else if (resolved_dynly)
 		{
 		  outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
 		  outrel.r_addend = rel->r_addend;
@@ -2093,6 +2210,25 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 					      bfd_reloc_notsupported,
 					      is_undefweak, name,
 					      "Internal:");
+	  if (resolved_local)
+	    {
+	      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, "TLS section not be created");
+		}
+	      else
+		relocation -= elf_hash_table (info)->tls_sec->vma;
+	    }
+	  else
+	    {
+	    fatal = loongarch_reloc_is_fatal (info, input_bfd,
+		      input_section, rel, howto, bfd_reloc_undefined,
+		      is_undefweak, name,
+		      "TLS LE just can be resolved local only.");
+	    }
+
 	  break;
 
 	case R_LARCH_SOP_PUSH_TLS_TPREL:
@@ -2275,7 +2411,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	    {
 	      off = h->got.offset;
 
-	      if (off == MINUS_ONE)
+	      if (off == MINUS_ONE
+		  && h->type != STT_GNU_IFUNC)
 		{
 		  fatal = (loongarch_reloc_is_fatal
 			   (info, input_bfd, input_section, rel, howto,
@@ -2284,6 +2421,33 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		  break;
 		}
 
+	      /* Hidden symbol not has .got entry, only .got.plt entry
+		 so gprel is (plt - got).  */
+	      if (off == MINUS_ONE
+		  && h->type == STT_GNU_IFUNC)
+		{
+		  if (h->plt.offset == (bfd_vma) -1)
+		    {
+		      abort();
+		    }
+
+		  bfd_vma plt_index = h->plt.offset / PLT_ENTRY_SIZE;
+		  off = plt_index * GOT_ENTRY_SIZE;
+
+		  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);
+		    }
+		  else
+		    {
+		      /* Section iplt not has plt header.  */
+		      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)))
 		{
@@ -2321,6 +2485,28 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		    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)
+			    {
+			      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);
+			}
 		      bfd_put_NN (output_bfd, relocation, got->contents + off);
 		      h->got.offset |= 1;
 		    }
@@ -2516,9 +2702,19 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		    }
 		  else /* if (resolved_dynly) */
 		    {
-		      outrel.r_info =
-			ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_TPRELNN);
-		      outrel.r_addend = 0;
+		      /* 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
+			{
+			  outrel.r_info =
+			    ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_TPRELNN);
+			  outrel.r_addend = 0;
+			}
 		      loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
 						 &outrel);
 		    }
@@ -2628,22 +2824,16 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
 {
   struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
   const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
-  asection *plt = NULL;
 
   if (h->plt.offset != MINUS_ONE)
     {
       size_t i, plt_idx;
-      asection *gotplt, *relplt;
+      asection *plt, *gotplt, *relplt;
       bfd_vma got_address;
       uint32_t plt_entry[PLT_ENTRY_INSNS];
       bfd_byte *loc;
       Elf_Internal_Rela rela;
 
-      plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
-
-      /* One of '.plt' and '.iplt' represents.  */
-      BFD_ASSERT (!!htab->elf.splt ^ !!htab->elf.iplt);
-
       if (htab->elf.splt)
 	{
 	  BFD_ASSERT ((h->type == STT_GNU_IFUNC
@@ -2653,6 +2843,7 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
 	  plt = htab->elf.splt;
 	  gotplt = htab->elf.sgotplt;
 	  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;
 	}
@@ -2664,6 +2855,7 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
 	  plt = htab->elf.iplt;
 	  gotplt = htab->elf.igotplt;
 	  relplt = htab->elf.irelplt;
+	  plt_idx = h->plt.offset / PLT_ENTRY_SIZE;
 	  got_address = sec_addr (gotplt) + plt_idx * GOT_ENTRY_SIZE;
 	}
 
@@ -2684,7 +2876,9 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
       bfd_put_NN (output_bfd, sec_addr (plt), loc);
 
       rela.r_offset = got_address;
-      if (h->type == STT_GNU_IFUNC && SYMBOL_REFERENCES_LOCAL (info, h))
+
+      /* 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
@@ -2733,26 +2927,50 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
 
       rela.r_offset = sec_addr (sgot) + off;
 
-      if (h->type == STT_GNU_IFUNC)
+      if (h->def_regular
+	  && h->type == STT_GNU_IFUNC)
 	{
-	  if (elf_hash_table (info)->dynamic_sections_created
-	      && SYMBOL_REFERENCES_LOCAL (info, h))
+	  if(h->plt.offset == MINUS_ONE)
+	    {
+	      if (htab->elf.splt == NULL)
+		srela = htab->elf.irelplt;
+
+	      if (SYMBOL_REFERENCES_LOCAL (info, h))
+		{
+		  asection *sec = h->root.u.def.section;
+		  rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
+		  rela.r_addend = h->root.u.def.value + sec->output_section->vma
+		    + sec->output_offset;
+		  bfd_put_NN (output_bfd, 0, sgot->contents + off);
+		}
+	      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;
+		  bfd_put_NN (output_bfd, (bfd_vma) 0, sgot->contents + off);
+		}
+	    }
+	  else if(bfd_link_pic (info))
 	    {
-	      asection *sec = h->root.u.def.section;
-	      rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
-	      rela.r_addend = (h->root.u.def.value + sec->output_section->vma
-			       + sec->output_offset);
-	      bfd_put_NN (output_bfd, 0, sgot->contents + off);
+	      rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
+	      rela.r_addend = 0;
+	      bfd_put_NN (output_bfd, rela.r_addend, sgot->contents + off);
 	    }
 	  else
 	    {
-	      BFD_ASSERT (plt);
-	      rela.r_info
-		= ELFNN_R_INFO (0, (bfd_link_pic (info)
-				    ? R_LARCH_RELATIVE : R_LARCH_NONE));
-	      rela.r_addend =
-		plt->output_section->vma + plt->output_offset + h->plt.offset;
-	      bfd_put_NN (output_bfd, rela.r_addend, sgot->contents + off);
+	      asection *plt;
+	      /* For non-shared object, we can't use .got.plt, which
+		 contains the real function address if we need pointer
+		 equality.  We load the GOT entry with the PLT entry.  */
+	      plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
+	      bfd_put_NN (output_bfd,
+			  (plt->output_section->vma
+			   + plt->output_offset
+			   + h->plt.offset),
+			  sgot->contents + off);
+	      return true;
 	    }
 	}
       else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))
@@ -2885,10 +3103,8 @@ loongarch_elf_finish_dynamic_sections (bfd *output_bfd,
 	return false;
     }
 
-  if ((plt = htab->elf.splt))
-    gotplt = htab->elf.sgotplt;
-  else if ((plt = htab->elf.iplt))
-    gotplt = htab->elf.igotplt;
+  plt = htab->elf.splt;
+  gotplt = htab->elf.sgotplt;
 
   if (plt && 0 < plt->size)
     {
@@ -3017,10 +3233,10 @@ loongarch_elf_copy_indirect_symbol (struct bfd_link_info *info,
 				    struct elf_link_hash_entry *dir,
 				    struct elf_link_hash_entry *ind)
 {
-  struct loongarch_elf_link_hash_entry *edir, *eind;
+  struct elf_link_hash_entry *edir, *eind;
 
-  edir = (struct loongarch_elf_link_hash_entry *) dir;
-  eind = (struct loongarch_elf_link_hash_entry *) ind;
+  edir = dir;
+  eind = ind;
 
   if (eind->dyn_relocs != NULL)
     {
@@ -3055,8 +3271,9 @@ loongarch_elf_copy_indirect_symbol (struct bfd_link_info *info,
 
   if (ind->root.type == bfd_link_hash_indirect && dir->got.refcount < 0)
     {
-      edir->tls_type = eind->tls_type;
-      eind->tls_type = GOT_UNKNOWN;
+      loongarch_elf_hash_entry(edir)->tls_type
+	= loongarch_elf_hash_entry(eind)->tls_type;
+      loongarch_elf_hash_entry(eind)->tls_type = GOT_UNKNOWN;
     }
   _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 }
diff --git a/bfd/elfxx-loongarch.h b/bfd/elfxx-loongarch.h
index 3b5c6361e06..8ea63d03fa5 100644
--- a/bfd/elfxx-loongarch.h
+++ b/bfd/elfxx-loongarch.h
@@ -31,3 +31,11 @@ extern reloc_howto_type *
 loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *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.  */
+#define PLT_LOCAL_IFUNC_P(INFO, H) \
+  ((H)->dynindx == -1 \
+   || ((bfd_link_executable (INFO) \
+	|| ELF_ST_VISIBILITY ((H)->other) != STV_DEFAULT) \
+	&& (H)->def_regular \
+	&& (H)->type == STT_GNU_IFUNC))
-- 
2.31.1


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-03-12  7:45 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-12  7:44 [PATCH] LoongArch: Fix LD check fails liuzhensong

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