[PATCH] x86: Don't call strncmp for __tls_get_addr

H.J. Lu hjl.tools@gmail.com
Fri Aug 4 04:26:00 GMT 2017


I am testing this patch.

H.J.
---
Instead of calling strncmp for each symbol, we can check for
__tls_get_addr reference once.

	* elf32-i386.c (elf_i386_link_hash_entry): Change tls_get_addr
	to 1 bit.
	(elf_i386_link_hash_newfunc): Initialize tls_get_addr to 0.
	(elf_i386_check_tls_transition): Check tls_get_addr directly.
	(elf_i386_convert_load_reloc): Update tls_get_addr check.
	(elf_i386_link_check_relocs): New function.
	(bfd_elf32_bfd_link_check_relocs): New.
	* elf64-x86-64.c (elf_x86_64_link_hash_entry): Change tls_get_addr
	to 1 bit.
	(elf_x86_64_link_hash_newfunc): Initialize tls_get_addr to 0.
	(elf_x86_64_check_tls_transition): Check tls_get_addr directly.
	(elf_x86_64_convert_load_reloc): Update tls_get_addr check.
	(elf_x86_64_link_check_relocs): New function.
	(bfd_elf64_bfd_link_check_relocs): New.
	(bfd_elf32_bfd_link_check_relocs): Likewise.
---
 bfd/elf32-i386.c   | 54 ++++++++++++++++++++++++----------------------------
 bfd/elf64-x86-64.c | 56 ++++++++++++++++++++++++++----------------------------
 2 files changed, 52 insertions(+), 58 deletions(-)

diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 37099b7557..14f018ea2c 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -995,10 +995,8 @@ struct elf_i386_link_hash_entry
   /* Don't call finish_dynamic_symbol on this symbol.  */
   unsigned int no_finish_dynamic_symbol : 1;
 
-  /* 0: symbol isn't ___tls_get_addr.
-     1: symbol is ___tls_get_addr.
-     2: symbol is unknown.  */
-  unsigned int tls_get_addr : 2;
+  /* TRUE if symbol symbol is __tls_get_addr.  */
+  unsigned int tls_get_addr : 1;
 
   /* Reference count of C/C++ function pointer relocations in read-write
      section which can be resolved at run-time.  */
@@ -1149,7 +1147,7 @@ elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry,
       eh->has_got_reloc = 0;
       eh->has_non_got_reloc = 0;
       eh->no_finish_dynamic_symbol = 0;
-      eh->tls_get_addr = 2;
+      eh->tls_get_addr = 0;
       eh->func_pointer_refcount = 0;
       eh->plt_got.offset = (bfd_vma) -1;
       eh->tlsdesc_got = (bfd_vma) -1;
@@ -1378,7 +1376,7 @@ elf_i386_check_tls_transition (asection *sec,
   struct elf_link_hash_entry *h;
   bfd_vma offset;
   bfd_byte *call;
-  bfd_boolean indirect_call, tls_get_addr;
+  bfd_boolean indirect_call;
 
   offset = rel->r_offset;
   switch (r_type)
@@ -1483,29 +1481,9 @@ elf_i386_check_tls_transition (asection *sec,
       if (r_symndx < symtab_hdr->sh_info)
 	return FALSE;
 
-      tls_get_addr = FALSE;
       h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-      if (h != NULL && h->root.root.string != NULL)
-	{
-	  struct elf_i386_link_hash_entry *eh
-	    = (struct elf_i386_link_hash_entry *) h;
-	  tls_get_addr = eh->tls_get_addr == 1;
-	  if (eh->tls_get_addr > 1)
-	    {
-	      /* Use strncmp to check ___tls_get_addr since
-		 ___tls_get_addr may be versioned.  */
-	      if (strncmp (h->root.root.string, "___tls_get_addr", 15)
-		  == 0)
-		{
-		  eh->tls_get_addr = 1;
-		  tls_get_addr = TRUE;
-		}
-	      else
-		eh->tls_get_addr = 0;
-	    }
-	}
-
-      if (!tls_get_addr)
+      if (h == NULL
+	  || !((struct elf_i386_link_hash_entry *) h)->tls_get_addr)
 	return FALSE;
       else if (indirect_call)
 	return (ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32X);
@@ -1863,7 +1841,7 @@ convert_branch:
 	      modrm = 0xe8;
 	      /* To support TLS optimization, always use addr32 prefix
 		 for "call *___tls_get_addr@GOT(%reg)".  */
-	      if (eh && eh->tls_get_addr == 1)
+	      if (eh && eh->tls_get_addr)
 		{
 		  nop = 0x67;
 		  nop_offset = irel->r_offset - 2;
@@ -7148,6 +7126,23 @@ error_alignment:
   return pbfd;
 }
 
+static bfd_boolean
+elf_i386_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
+{
+  if (!bfd_link_relocatable (info))
+    {
+      /* Check for ___tls_get_addr reference.  */
+      struct elf_link_hash_entry *h;
+      h = elf_link_hash_lookup (elf_hash_table (info), "___tls_get_addr",
+				FALSE, FALSE, FALSE);
+      if (h != NULL)
+	((struct elf_i386_link_hash_entry *) h)->tls_get_addr = 1;
+    }
+
+  /* Invoke the regular ELF backend linker to do all the work.  */
+  return _bfd_elf_link_check_relocs (abfd, info);
+}
+
 #define TARGET_LITTLE_SYM		i386_elf32_vec
 #define TARGET_LITTLE_NAME		"elf32-i386"
 #define ELF_ARCH			bfd_arch_i386
@@ -7178,6 +7173,7 @@ error_alignment:
 #define bfd_elf32_bfd_reloc_type_lookup	      elf_i386_reloc_type_lookup
 #define bfd_elf32_bfd_reloc_name_lookup	      elf_i386_reloc_name_lookup
 #define bfd_elf32_get_synthetic_symtab	      elf_i386_get_synthetic_symtab
+#define bfd_elf32_bfd_link_check_relocs	      elf_i386_link_check_relocs
 
 #define elf_backend_adjust_dynamic_symbol     elf_i386_adjust_dynamic_symbol
 #define elf_backend_relocs_compatible	      _bfd_elf_relocs_compatible
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 448599eb9b..e5f4681354 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1101,10 +1101,8 @@ struct elf_x86_64_link_hash_entry
   /* Don't call finish_dynamic_symbol on this symbol.  */
   unsigned int no_finish_dynamic_symbol : 1;
 
-  /* 0: symbol isn't __tls_get_addr.
-     1: symbol is __tls_get_addr.
-     2: symbol is unknown.  */
-  unsigned int tls_get_addr : 2;
+  /* TRUE if symbol symbol is __tls_get_addr.  */
+  unsigned int tls_get_addr : 1;
 
   /* Reference count of C/C++ function pointer relocations in read-write
      section which can be resolved at run-time.  */
@@ -1264,7 +1262,7 @@ elf_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry,
       eh->has_got_reloc = 0;
       eh->has_non_got_reloc = 0;
       eh->no_finish_dynamic_symbol = 0;
-      eh->tls_get_addr = 2;
+      eh->tls_get_addr = 0;
       eh->func_pointer_refcount = 0;
       eh->plt_second.offset = (bfd_vma) -1;
       eh->plt_got.offset = (bfd_vma) -1;
@@ -1527,7 +1525,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
   bfd_vma offset;
   struct elf_x86_64_link_hash_table *htab;
   bfd_byte *call;
-  bfd_boolean indirect_call, tls_get_addr;
+  bfd_boolean indirect_call;
 
   htab = elf_x86_64_hash_table (info);
   offset = rel->r_offset;
@@ -1667,29 +1665,9 @@ elf_x86_64_check_tls_transition (bfd *abfd,
       if (r_symndx < symtab_hdr->sh_info)
 	return FALSE;
 
-      tls_get_addr = FALSE;
       h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-      if (h != NULL && h->root.root.string != NULL)
-	{
-	  struct elf_x86_64_link_hash_entry *eh
-	    = (struct elf_x86_64_link_hash_entry *) h;
-	  tls_get_addr = eh->tls_get_addr == 1;
-	  if (eh->tls_get_addr > 1)
-	    {
-	      /* Use strncmp to check __tls_get_addr since
-		 __tls_get_addr may be versioned.  */
-	      if (strncmp (h->root.root.string, "__tls_get_addr", 14)
-		  == 0)
-		{
-		  eh->tls_get_addr = 1;
-		  tls_get_addr = TRUE;
-		}
-	      else
-		eh->tls_get_addr = 0;
-	    }
-	}
-
-      if (!tls_get_addr)
+      if (h == NULL
+	  || !((struct elf_x86_64_link_hash_entry *) h)->tls_get_addr)
 	return FALSE;
       else if (largepic)
 	return ELF32_R_TYPE (rel[1].r_info) == R_X86_64_PLTOFF64;
@@ -2253,7 +2231,7 @@ convert:
 	  modrm = 0xe8;
 	  /* To support TLS optimization, always use addr32 prefix for
 	     "call *__tls_get_addr@GOTPCREL(%rip)".  */
-	  if (eh && eh->tls_get_addr == 1)
+	  if (eh && eh->tls_get_addr)
 	    {
 	      nop = 0x67;
 	      nop_offset = irel->r_offset - 2;
@@ -7715,6 +7693,23 @@ error_alignment:
   return pbfd;
 }
 
+static bfd_boolean
+elf_x86_64_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
+{
+  if (!bfd_link_relocatable (info))
+    {
+      /* Check for __tls_get_addr reference.  */
+      struct elf_link_hash_entry *h;
+      h = elf_link_hash_lookup (elf_hash_table (info), "__tls_get_addr",
+				FALSE, FALSE, FALSE);
+      if (h != NULL)
+	((struct elf_x86_64_link_hash_entry *) h)->tls_get_addr = 1;
+    }
+
+  /* Invoke the regular ELF backend linker to do all the work.  */
+  return _bfd_elf_link_check_relocs (abfd, info);
+}
+
 static const struct bfd_elf_special_section
 elf_x86_64_special_sections[]=
 {
@@ -7779,6 +7774,7 @@ elf_x86_64_special_sections[]=
 #define elf_backend_object_p		    elf64_x86_64_elf_object_p
 #define bfd_elf64_mkobject		    elf_x86_64_mkobject
 #define bfd_elf64_get_synthetic_symtab	    elf_x86_64_get_synthetic_symtab
+#define bfd_elf64_bfd_link_check_relocs	    elf_x86_64_link_check_relocs
 
 #define elf_backend_section_from_shdr \
 	elf_x86_64_section_from_shdr
@@ -8078,6 +8074,8 @@ elf32_x86_64_nacl_elf_object_p (bfd *abfd)
   elf_x86_64_mkobject
 #define bfd_elf32_get_synthetic_symtab \
   elf_x86_64_get_synthetic_symtab
+#define bfd_elf32_bfd_link_check_relocs \
+  elf_x86_64_link_check_relocs
 
 #undef elf_backend_object_p
 #define elf_backend_object_p \
-- 
2.13.3



More information about the Binutils mailing list