[6/6,ARC] More fixes for TLS.

Message ID 20181115154430.23071-7-claziss@gmail.com
State New
Headers show
Series
  • Backports from mainline.
Related show

Commit Message

Claudiu Zissulescu Nov. 15, 2018, 3:44 p.m.
From: Cupertino Miranda <cmiranda@synopsys.com>


Added warning for static TLS reloc.

Fixed issue related to TLS and partial static linking of libraries:
  This issue was detected when throwing exceptions in C++ while linking with
  -static-libstdc++.
  TLS relocation from the libstdc++ wasn't being patched as local now that it was
  static linked with the executable.

Fix for TLS with static and pie. Problem introduced by earlier patch:
  Fixes the following glibc tests:
   - elf/tst-tls1-static

bfd/
    xxxx-xx-xx  Cupertino Miranda  <cmiranda@synopsys.com>

	    * arc-got.h (arc_got_entry_type_for_reloc): Changed to
	      correct static TLS relocs.
            * elf32-arc.c (elf_arc_check_relocs): Introduced warning to
	      TLS relocs which require -fPIC.
	      (arc_create_forced_local_got_entries_for_tls): Created.
	      Traverses list of GOT entries to be resolved statically
	      when needed.
	      (elf_arc_finish_dynamic_sections): Changed. Calls
	      arc_create_forced_local_got_entries_for_tls for each known
	      possibly GOT symbol.
---
 bfd/ChangeLog   |  15 +++++++
 bfd/arc-got.h   |  33 ++++++++------
 bfd/elf32-arc.c | 117 +++++++++++++++++++++++++++++++++++-------------
 3 files changed, 121 insertions(+), 44 deletions(-)

-- 
2.19.1

Patch

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 09091f65ae..53bb9ebca1 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,18 @@ 
+2018-11-15  Claudiu Zissulescu  <claziss@synopsys.com>
+
+	Backport from mainline
+	2018-11-09  Cupertino Miranda  <cmiranda@synopsys.com>
+	* arc-got.h (arc_got_entry_type_for_reloc): Changed to
+	  correct static TLS relocs.
+	* elf32-arc.c (elf_arc_check_relocs): Introduced warning to
+	  TLS relocs which require -fPIC.
+	  (arc_create_forced_local_got_entries_for_tls): Created.
+	  Traverses list of GOT entries to be resolved statically
+	  when needed.
+	  (elf_arc_finish_dynamic_sections): Changed. Calls
+	  arc_create_forced_local_got_entries_for_tls for each known
+	  possibly GOT symbol.
+
 2018-11-15  Claudiu Zissulescu  <claziss@synopsys.com>
 
 	Backport from mainline
diff --git a/bfd/arc-got.h b/bfd/arc-got.h
index 69e9aa3275..253578b90c 100644
--- a/bfd/arc-got.h
+++ b/bfd/arc-got.h
@@ -208,7 +208,7 @@  arc_got_entry_type_for_reloc (reloc_howto_type *howto)
 		     __LINE__, name_for_global_symbol (H));		\
       }									\
     if (H)								\
-      if (h->dynindx == -1 && !h->forced_local)				\
+      if (H->dynindx == -1 && !H->forced_local)				\
 	if (! bfd_elf_link_record_dynamic_symbol (info, H))		\
 	  return FALSE;							\
      htab->s##SECNAME->size += 4;					\
@@ -284,6 +284,7 @@  relocate_fix_got_relocs_for_got_info (struct got_entry **	   list_p,
   BFD_ASSERT (entry);
 
   if (h == NULL
+      || h->forced_local == TRUE
       || (! elf_hash_table (info)->dynamic_sections_created
 	  || (bfd_link_pic (info)
 	      && SYMBOL_REFERENCES_LOCAL (info, h))))
@@ -331,27 +332,31 @@  relocate_fix_got_relocs_for_got_info (struct got_entry **	   list_p,
 		BFD_ASSERT (tls_sec && tls_sec->output_section);
 		bfd_vma sec_vma = tls_sec->output_section->vma;
 
-		bfd_put_32 (output_bfd,
+		if (h == NULL || h->forced_local
+		   || !elf_hash_table (info)->dynamic_sections_created)
+		  {
+		    bfd_put_32 (output_bfd,
 			    sym_value - sec_vma
 			    + (elf_hash_table (info)->dynamic_sections_created
 			       ? 0
-			       : (align_power (TCB_SIZE,
+			       : (align_power (0,
 					       tls_sec->alignment_power))),
 			    htab->sgot->contents + entry->offset
 			    + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
 			       ? 4 : 0));
 
-		ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx "
-			   "@ %lx, for symbol %s\n",
-			   (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" :
-			    "GOT_TLS_IE"),
-			   (long) (sym_value - sec_vma),
-			   (long) (htab->sgot->output_section->vma
-			      + htab->sgot->output_offset
-			      + entry->offset
-			      + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
-				 ? 4 : 0)),
-			   symbol_name);
+		    ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx "
+			  "@ %lx, for symbol %s\n",
+			  (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" :
+			   "GOT_TLS_IE"),
+			  (long) (sym_value - sec_vma),
+			  (long) (htab->sgot->output_section->vma
+			     + htab->sgot->output_offset
+			     + entry->offset
+			     + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
+				? 4 : 0)),
+			  symbol_name);
+		  }
 	      }
 	      break;
 
diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c
index bde142f37f..495fa342d3 100644
--- a/bfd/elf32-arc.c
+++ b/bfd/elf32-arc.c
@@ -1973,36 +1973,35 @@  elf_arc_check_relocs (bfd *			 abfd,
 
       switch (r_type)
 	{
-	  case R_ARC_32:
-	  case R_ARC_32_ME:
-	    /* During shared library creation, these relocs should not
-	       appear in a shared library (as memory will be read only
-	       and the dynamic linker can not resolve these.  However
-	       the error should not occur for e.g. debugging or
-	       non-readonly sections.  */
-	    if (h != NULL
-		&& (bfd_link_dll (info) && !bfd_link_pie (info))
-		&& (sec->flags & SEC_ALLOC) != 0
-		&& (sec->flags & SEC_READONLY) != 0
-		&& ((sec->flags & SEC_CODE) != 0
-		    || (sec->flags & SEC_DEBUGGING) != 0))
-	      {
-		const char *name;
-		if (h)
-		  name = h->root.root.string;
-		else
-		  /* bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);  */
-		  name = "UNKNOWN";
-		_bfd_error_handler
-		  /* xgettext:c-format */
-		  (_("%pB: relocation %s against `%s' can not be used"
-		     " when making a shared object; recompile with -fPIC"),
-		   abfd,
-		   arc_elf_howto (r_type)->name,
-		   name);
-		bfd_set_error (bfd_error_bad_value);
-		return FALSE;
-	      }
+	case R_ARC_32:
+	case R_ARC_32_ME:
+	  /* During shared library creation, these relocs should not
+	     appear in a shared library (as memory will be read only
+	     and the dynamic linker can not resolve these.  However
+	     the error should not occur for e.g. debugging or
+	     non-readonly sections.  */
+	  if (h != NULL
+	      && (bfd_link_dll (info) && !bfd_link_pie (info))
+	      && (sec->flags & SEC_ALLOC) != 0
+	      && (sec->flags & SEC_READONLY) != 0
+	      && ((sec->flags & SEC_CODE) != 0
+		  || (sec->flags & SEC_DEBUGGING) != 0))
+	    {
+	      const char *name;
+	      if (h)
+		name = h->root.root.string;
+	      else
+		name = "UNKNOWN";
+	      _bfd_error_handler
+	      /* xgettext:c-format */
+	      (_("%pB: relocation %s against `%s' can not be used"
+		 " when making a shared object; recompile with -fPIC"),
+		 abfd,
+		 arc_elf_howto (r_type)->name,
+		 name);
+	      bfd_set_error (bfd_error_bad_value);
+	      return FALSE;
+	    }
 
 	    /* In some cases we are not setting the 'non_got_ref'
 	       flag, even though the relocations don't require a GOT
@@ -2052,6 +2051,25 @@  elf_arc_check_relocs (bfd *			 abfd,
       if (is_reloc_for_GOT (howto)
 	  || is_reloc_for_TLS (howto))
 	{
+	  if (bfd_link_dll (info) && !bfd_link_pie (info)
+	      && (r_type == R_ARC_TLS_LE_32 || r_type == R_ARC_TLS_LE_S9))
+	    {
+	      const char *name;
+	      if (h)
+		name = h->root.root.string;
+	      else
+		/* bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);  */
+		name = "UNKNOWN";
+	      _bfd_error_handler
+		/* xgettext:c-format */
+		(_("%pB: relocation %s against `%s' can not be used"
+		   " when making a shared object; recompile with -fPIC"),
+		   abfd,
+		   arc_elf_howto (r_type)->name,
+		   name);
+	      bfd_set_error (bfd_error_bad_value);
+	      return FALSE;
+	    }
 	  if (! _bfd_elf_create_got_section (dynobj, info))
 	    return FALSE;
 
@@ -2474,6 +2492,39 @@  elf_arc_finish_dynamic_symbol (bfd * output_bfd,
     s = bfd_get_linker_section (dynobj, SECTION);		\
   break;
 
+
+struct obfd_info_group {
+  bfd *output_bfd;
+  struct bfd_link_info *info;
+};
+
+static bfd_boolean
+arc_create_forced_local_got_entries_for_tls (struct bfd_hash_entry *bh,
+					     void *data)
+{
+  struct elf_arc_link_hash_entry * h =
+    (struct elf_arc_link_hash_entry *) bh;
+  struct obfd_info_group *tmp = (struct obfd_info_group *) data;
+
+  if (h->got_ents != NULL)
+    {
+      BFD_ASSERT (h);
+
+      struct got_entry *list = h->got_ents;
+
+      while (list != NULL)
+	{
+	  create_got_dynrelocs_for_single_entry (list, tmp->output_bfd,
+	    tmp->info,
+	    (struct elf_link_hash_entry *) h);
+	  list = list->next;
+	}
+    }
+
+  return TRUE;
+}
+
+
 /* Function :  elf_arc_finish_dynamic_sections
    Brief    :  Finish up the dynamic sections handling.
    Args     :  output_bfd :
@@ -2607,6 +2658,12 @@  elf_arc_finish_dynamic_sections (bfd * output_bfd,
 	}
     }
 
+  struct obfd_info_group group;
+  group.output_bfd = output_bfd;
+  group.info = info;
+  bfd_hash_traverse (&info->hash->table,
+		     arc_create_forced_local_got_entries_for_tls, &group);
+
   return TRUE;
 }