Factor our stub creation in ARM backend
authorThomas Preud'homme <thomas.preudhomme@arm.com>
Tue, 10 May 2016 14:42:20 +0000 (15:42 +0100)
committerThomas Preud'homme <thomas.preudhomme@arm.com>
Tue, 10 May 2016 14:42:20 +0000 (15:42 +0100)
2016-05-10  Thomas Preud'homme  <thomas.preudhomme@arm.com>

bfd/
* elf32-arm.c (elf32_arm_create_stub): New function.
(elf32_arm_size_stubs): Use elf32_arm_create_stub for stub creation.

bfd/ChangeLog
bfd/elf32-arm.c

index 0e10d3aef4e5a968f453c3405846ac837df93066..7e89254380b41c9908e67aa21924e7f37a364fef 100644 (file)
@@ -1,3 +1,8 @@
+2016-05-10  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       * elf32-arm.c (elf32_arm_create_stub): New function.
+       (elf32_arm_size_stubs): Use elf32_arm_create_stub for stub creation.
+
 2016-05-10  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * elf32-arm.c (enum elf32_arm_stub_type): Delete
index 5f6941dbacc166dba354502cebfc10cf1bf2db5d..9adc43e69cf1ff0c04839e494d8945110de406e2 100644 (file)
@@ -5107,6 +5107,103 @@ cortex_a8_erratum_scan (bfd *input_bfd,
   return FALSE;
 }
 
+/* Create or update a stub entry depending on whether the stub can already be
+   found in HTAB.  The stub is identified by:
+   - its type STUB_TYPE
+   - its source branch (note that several can share the same stub) whose
+     section and relocation (if any) are given by SECTION and IRELA
+     respectively
+   - its target symbol whose input section, hash, name, value and branch type
+     are given in SYM_SEC, HASH, SYM_NAME, SYM_VALUE and BRANCH_TYPE
+     respectively
+
+   If found, the value of the stub's target symbol is updated from SYM_VALUE
+   and *NEW_STUB is set to FALSE.  Otherwise, *NEW_STUB is set to
+   TRUE and the stub entry is initialized.
+
+   Returns whether the stub could be successfully created or updated, or FALSE
+   if an error occured.  */
+
+static bfd_boolean
+elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
+                      enum elf32_arm_stub_type stub_type, asection *section,
+                      Elf_Internal_Rela *irela, asection *sym_sec,
+                      struct elf32_arm_link_hash_entry *hash, char *sym_name,
+                      bfd_vma sym_value, enum arm_st_branch_type branch_type,
+                      bfd_boolean *new_stub)
+{
+  const asection *id_sec;
+  char *stub_name;
+  struct elf32_arm_stub_hash_entry *stub_entry;
+  unsigned int r_type;
+
+  BFD_ASSERT (stub_type != arm_stub_none);
+  *new_stub = FALSE;
+
+  BFD_ASSERT (irela);
+  BFD_ASSERT (section);
+
+  /* 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;
+
+  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);
+      stub_entry->target_value = sym_value;
+      return TRUE;
+    }
+
+  stub_entry = elf32_arm_add_stub (stub_name, section, htab);
+  if (stub_entry == NULL)
+    {
+      free (stub_name);
+      return FALSE;
+    }
+
+  stub_entry->target_value = sym_value;
+  stub_entry->target_section = sym_sec;
+  stub_entry->stub_type = stub_type;
+  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)
+    {
+      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);
+
+  *new_stub = TRUE;
+  return TRUE;
+}
+
 /* Determine and set the size of the stub section for a final link.
 
    The basic idea here is to examine all the relocations looking for
@@ -5250,14 +5347,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
                {
                  unsigned int r_type, r_indx;
                  enum elf32_arm_stub_type stub_type;
-                 struct elf32_arm_stub_hash_entry *stub_entry;
                  asection *sym_sec;
                  bfd_vma sym_value;
                  bfd_vma destination;
                  struct elf32_arm_link_hash_entry *hash;
                  const char *sym_name;
-                 char *stub_name;
-                 const asection *id_sec;
                  unsigned char st_type;
                  enum arm_st_branch_type branch_type;
                  bfd_boolean created_stub = FALSE;
@@ -5446,6 +5540,8 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
                  do
                    {
+                     bfd_boolean new_stub;
+
                      /* Determine what (if any) linker stub is needed.  */
                      stub_type = arm_type_of_stub (info, section, irela,
                                                    st_type, &branch_type,
@@ -5454,74 +5550,20 @@ elf32_arm_size_stubs (bfd *output_bfd,
                      if (stub_type == arm_stub_none)
                        break;
 
-                     /* 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)
-                       goto error_ret_free_internal;
-
                      /* We've either created a stub for this reloc already,
                         or we are about to.  */
-                     created_stub = TRUE;
-
-                     stub_entry = arm_stub_hash_lookup
-                                    (&htab->stub_hash_table, stub_name,
-                                     FALSE, FALSE);
-                     if (stub_entry != NULL)
-                       {
-                         /* The proper stub has already been created.  */
-                         free (stub_name);
-                         stub_entry->target_value = sym_value;
-                         break;
-                       }
+                     created_stub =
+                       elf32_arm_create_stub (htab, stub_type, section, irela,
+                                              sym_sec, hash,
+                                              (char *) sym_name, sym_value,
+                                              branch_type, &new_stub);
 
-                     stub_entry = elf32_arm_add_stub (stub_name, section,
-                                                      htab);
-                     if (stub_entry == NULL)
-                       {
-                         free (stub_name);
-                         goto error_ret_free_internal;
-                       }
-
-                     stub_entry->target_value = sym_value;
-                     stub_entry->target_section = sym_sec;
-                     stub_entry->stub_type = stub_type;
-                     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)
-                       {
-                         free (stub_name);
-                         goto error_ret_free_internal;
-                       }
-
-                     /* For historical reasons, use the existing names for
-                        ARM-to-Thumb and Thumb-to-ARM stubs.  */
-                     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);
+                     if (!created_stub)
+                       goto error_ret_free_internal;
+                     else if (!new_stub)
+                       break;
                      else
-                       sprintf (stub_entry->output_name, STUB_ENTRY_NAME,
-                                sym_name);
-
-                     stub_changed = TRUE;
+                       stub_changed = TRUE;
                    }
                  while (0);