This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC PATCH, binutils, ARM 5/9] Allow veneers to claim veneered symbols


Hi,

[Posting patch series as RFC]

This patch is part of a patch series to add support for ARMv8-M security extension[1] to GNU ld. This specific patch add infrastructure to allow a veneer to take over the symbol of the code it is veneering, as required for Secure Gateway veneers.


[1] Software requirements for ARMv8-M security extension are described in document ARM-ECM-0359818 [2]
[2] Available on http://infocenter.arm.com in Developer guides and articles > Software development > ARMÂv8-M Security Extensions: Requirements on Development Tools

ChangeLog entry is as follows:


*** bfd/ChangeLog ***

2015-12-16  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * elf32-arm.c (arm_stub_sym_claimed): New function.
        (elf32_arm_create_stub): Use veneered symbol name and section if
        veneer needs to claim its symbol, and keep logic unchanged otherwise.
        (arm_claim_sym_one_stub): New function.
        (arm_map_one_stub): Call arm_claim_sym_one_stub if veneer needs to
        claim veneered symbol, otherwise create local symbol as before.


diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 6c8060a2c559ff5bd8a8e7f414f0a471dfa32cc8..11e6137732b420b49166567ce755fe413dab76cc 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -4259,6 +4259,41 @@ arm_stub_required_alignment (enum elf32_arm_stub_type stub_type)
     }
 }
 
+/* Returns whether stubs of type STUB_TYPE take over the symbol they are
+   veneering (TRUE) or have their own symbol (FALSE).  */
+
+static bfd_boolean
+arm_stub_sym_claimed (enum elf32_arm_stub_type stub_type)
+{
+  switch (stub_type)
+    {
+    case arm_stub_a8_veneer_b_cond:
+    case arm_stub_a8_veneer_b:
+    case arm_stub_a8_veneer_bl:
+    case arm_stub_long_branch_any_any:
+    case arm_stub_long_branch_v4t_arm_thumb:
+    case arm_stub_long_branch_thumb_only:
+    case arm_stub_long_branch_v4t_thumb_thumb:
+    case arm_stub_long_branch_v4t_thumb_arm:
+    case arm_stub_short_branch_v4t_thumb_arm:
+    case arm_stub_long_branch_any_arm_pic:
+    case arm_stub_long_branch_any_thumb_pic:
+    case arm_stub_long_branch_v4t_thumb_thumb_pic:
+    case arm_stub_long_branch_v4t_arm_thumb_pic:
+    case arm_stub_long_branch_v4t_thumb_arm_pic:
+    case arm_stub_long_branch_thumb_only_pic:
+    case arm_stub_long_branch_any_tls_pic:
+    case arm_stub_long_branch_v4t_thumb_tls_pic:
+    case arm_stub_a8_veneer_blx:
+    case arm_stub_long_branch_arm_nacl:
+    case arm_stub_long_branch_arm_nacl_pic:
+      return FALSE;
+
+    default:
+      abort ();  /* Should be unreachable.  */
+    }
+}
+
 static bfd_boolean
 arm_build_one_stub (struct bfd_hash_entry *gen_entry,
 		    void * in_arg)
@@ -5069,23 +5104,30 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
   BFD_ASSERT (stub_type != arm_stub_none);
   *new_stub = FALSE;
 
-  BFD_ASSERT (irela);
-  BFD_ASSERT (section);
+  if (arm_stub_sym_claimed (stub_type))
+    stub_name = sym_name;
+  else
+    {
+      BFD_ASSERT (irela);
+      BFD_ASSERT (section);
 
-  /* Support for grouping stub sections.  */
-  id_sec = htab->stub_group[section->id].link_sec;
+      /* Support for grouping stub sections.  */
+      id_sec = htab->stub_group[section->id].link_sec;
 
-  /* Get the name of this stub.  */
-  stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela, stub_type);
-  if (!stub_name)
-    return FALSE;
+      /* Get the name of this stub.  */
+      stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela,
+				       stub_type);
+      if (!stub_name)
+	return FALSE;
+    }
 
   stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name, FALSE,
 				     FALSE);
   /* The proper stub has already been created, just update its value.  */
   if (stub_entry != NULL)
     {
-      free (stub_name);
+      if (!arm_stub_sym_claimed (stub_type))
+	free (stub_name);
       stub_entry->target_value = sym_value;
       return TRUE;
     }
@@ -5093,7 +5135,8 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
   stub_entry = elf32_arm_add_stub (stub_name, section, htab);
   if (stub_entry == NULL)
     {
-      free (stub_name);
+      if (!arm_stub_sym_claimed (stub_type))
+	free (stub_name);
       return FALSE;
     }
 
@@ -5103,31 +5146,36 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
   stub_entry->h = hash;
   stub_entry->branch_type = branch_type;
 
-  if (sym_name == NULL)
-    sym_name = "unnamed";
-  stub_entry->output_name = (char *)
-    bfd_alloc (htab->stub_bfd, sizeof (THUMB2ARM_GLUE_ENTRY_NAME)
-				+ strlen (sym_name));
-  if (stub_entry->output_name == NULL)
+  if (arm_stub_sym_claimed (stub_type))
+    stub_entry->output_name = sym_name;
+  else
     {
-      free (stub_name);
-      return FALSE;
-    }
+      if (sym_name == NULL)
+	sym_name = "unnamed";
+      stub_entry->output_name = (char *)
+	bfd_alloc (htab->stub_bfd, sizeof (THUMB2ARM_GLUE_ENTRY_NAME)
+				   + strlen (sym_name));
+      if (stub_entry->output_name == NULL)
+	{
+	  free (stub_name);
+	  return FALSE;
+	}
 
-  /* For historical reasons, use the existing names for ARM-to-Thumb and
-     Thumb-to-ARM stubs.  */
-  r_type = ELF32_R_TYPE (irela->r_info);
-  if ((r_type == (unsigned int) R_ARM_THM_CALL
-      || r_type == (unsigned int) R_ARM_THM_JUMP24
-      || r_type == (unsigned int) R_ARM_THM_JUMP19)
-      && branch_type == ST_BRANCH_TO_ARM)
-    sprintf (stub_entry->output_name, THUMB2ARM_GLUE_ENTRY_NAME, sym_name);
-  else if ((r_type == (unsigned int) R_ARM_CALL
-	     || r_type == (unsigned int) R_ARM_JUMP24)
-	    && branch_type == ST_BRANCH_TO_THUMB)
-    sprintf (stub_entry->output_name, ARM2THUMB_GLUE_ENTRY_NAME, sym_name);
-  else
-    sprintf (stub_entry->output_name, STUB_ENTRY_NAME, sym_name);
+      /* For historical reasons, use the existing names for ARM-to-Thumb and
+	 Thumb-to-ARM stubs.  */
+      r_type = ELF32_R_TYPE (irela->r_info);
+      if ((r_type == (unsigned int) R_ARM_THM_CALL
+	   || r_type == (unsigned int) R_ARM_THM_JUMP24
+	   || r_type == (unsigned int) R_ARM_THM_JUMP19)
+	  && branch_type == ST_BRANCH_TO_ARM)
+	sprintf (stub_entry->output_name, THUMB2ARM_GLUE_ENTRY_NAME, sym_name);
+      else if ((r_type == (unsigned int) R_ARM_CALL
+		|| r_type == (unsigned int) R_ARM_JUMP24)
+	       && branch_type == ST_BRANCH_TO_THUMB)
+	sprintf (stub_entry->output_name, ARM2THUMB_GLUE_ENTRY_NAME, sym_name);
+      else
+	sprintf (stub_entry->output_name, STUB_ENTRY_NAME, sym_name);
+    }
 
   *new_stub = TRUE;
   return TRUE;
@@ -15705,6 +15753,22 @@ elf32_arm_output_plt_map (struct elf_link_hash_entry *h, void *inf)
 				     &h->plt, &eh->plt);
 }
 
+/* Bind a veneered symbol to its veneer identified by its hash entry
+   STUB_ENTRY.  The veneered location thus loose its symbol.  */
+
+static bfd_boolean
+arm_claim_sym_one_stub (struct elf32_arm_stub_hash_entry *stub_entry)
+{
+  struct elf32_arm_link_hash_entry *hash = stub_entry->h;
+
+  BFD_ASSERT (hash);
+  hash->root.root.u.def.section = stub_entry->stub_sec;
+  hash->root.root.u.def.value = stub_entry->stub_offset;
+  hash->root.size = stub_entry->stub_size;
+
+  return TRUE;
+}
+
 /* Output a single local symbol for a generated stub.  */
 
 static bfd_boolean
@@ -15751,24 +15815,30 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry,
     return TRUE;
 
   addr = (bfd_vma) stub_entry->stub_offset;
-  stub_name = stub_entry->output_name;
-
   template_sequence = stub_entry->stub_template;
-  switch (template_sequence[0].type)
+
+  if (arm_stub_sym_claimed (stub_entry->stub_type))
+    arm_claim_sym_one_stub (stub_entry);
+  else
     {
-    case ARM_TYPE:
-      if (!elf32_arm_output_stub_sym (osi, stub_name, addr, stub_entry->stub_size))
-	return FALSE;
-      break;
-    case THUMB16_TYPE:
-    case THUMB32_TYPE:
-      if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1,
-				      stub_entry->stub_size))
-	return FALSE;
-      break;
-    default:
-      BFD_FAIL ();
-      return 0;
+      stub_name = stub_entry->output_name;
+      switch (template_sequence[0].type)
+	{
+	case ARM_TYPE:
+	  if (!elf32_arm_output_stub_sym (osi, stub_name, addr,
+					  stub_entry->stub_size))
+	    return FALSE;
+	  break;
+	case THUMB16_TYPE:
+	case THUMB32_TYPE:
+	  if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1,
+					  stub_entry->stub_size))
+	    return FALSE;
+	  break;
+	default:
+	  BFD_FAIL ();
+	  return 0;
+	}
     }
 
   prev_type = DATA_TYPE;


The patch doesn't show any regression when running the binutils-gdb testsuite for the arm-none-eabi target.

Any comments?

Best regards,

Thomas


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]