* elf32-arm.c (elf32_arm_modify_segment_map): New function.
[deliverable/binutils-gdb.git] / bfd / elf32-arm.c
index cc3249662795b744765fda83896b45d4dbd63522..f438f03e7071cc754c707c65cad32e2e013550ab 100644 (file)
@@ -2350,9 +2350,10 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                                           (bfd_vma) 0);
        }
 
-      /* When generating a shared object, these relocations are copied
-        into the output file to be resolved at run time.  */
-      if (info->shared
+      /* When generating a shared object or relocatable executable, these
+        relocations are copied into the output file to be resolved at
+        run time.  */
+      if ((info->shared || globals->root.is_relocatable_executable)
          && (input_section->flags & SEC_ALLOC)
          && (r_type != R_ARM_REL32
              || !SYMBOL_CALLS_LOCAL (info, h))
@@ -3986,6 +3987,15 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
   htab = elf32_arm_hash_table (info);
   sreloc = NULL;
 
+  /* Create dynamic sections for relocatable executables so that we can
+     copy relocations.  */
+  if (htab->root.is_relocatable_executable
+      && ! htab->root.dynamic_sections_created)
+    {
+      if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
+       return FALSE;
+    }
+
   dynobj = elf_hash_table (info)->dynobj;
   local_got_offsets = elf_local_got_offsets (abfd);
 
@@ -4106,11 +4116,11 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
                  eh->plt_thumb_refcount += 1;
              }
 
-           /* If we are creating a shared library, and this is a reloc
-               against a global symbol, or a non PC relative reloc
-               against a local symbol, then we need to copy the reloc
-               into the shared library.  However, if we are linking with
-               -Bsymbolic, we do not need to copy a reloc against a
+           /* If we are creating a shared library or relocatable executable,
+              and this is a reloc against a global symbol, or a non PC
+              relative reloc against a local symbol, then we need to copy
+              the reloc into the shared library.  However, if we are linking
+              with -Bsymbolic, we do not need to copy a reloc against a
                global symbol which is defined in an object we are
                including in the link (i.e., DEF_REGULAR is set).  At
                this point we have not seen all the input files, so it is
@@ -4118,7 +4128,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
                later (it is never cleared).  We account for that
                possibility below by storing information in the
                relocs_copied field of the hash table entry.  */
-           if (info->shared
+           if ((info->shared || htab->root.is_relocatable_executable)
                && (sec->flags & SEC_ALLOC) != 0
                && ((r_type != R_ARM_PC24
                     && r_type != R_ARM_PLT32
@@ -4378,7 +4388,9 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
   asection * s;
   unsigned int power_of_two;
   struct elf32_arm_link_hash_entry * eh;
+  struct elf32_arm_link_hash_table *globals;
 
+  globals = elf32_arm_hash_table (info);
   dynobj = elf_hash_table (info)->dynobj;
 
   /* Make sure we know what is going on here.  */
@@ -4443,8 +4455,10 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
   /* If we are creating a shared library, we must presume that the
      only references to the symbol are via the global offset table.
      For such cases we need not do anything here; the relocations will
-     be handled correctly by relocate_section.  */
-  if (info->shared)
+     be handled correctly by relocate_section.  Relocatable executables
+     can reference data in shared objects directly, so we don't need to
+     do anything here.  */
+  if (info->shared || globals->root.is_relocatable_executable)
     return TRUE;
 
   /* We must allocate the symbol in our .dynbss section, which will
@@ -4637,13 +4651,23 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
      space for pc-relative relocs that have become local due to symbol
      visibility changes.  */
 
-  if (info->shared)
+  if (info->shared || htab->root.is_relocatable_executable)
     {
       /* Discard relocs on undefined weak syms with non-default
          visibility.  */
       if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
          && h->root.type == bfd_link_hash_undefweak)
        eh->relocs_copied = NULL;
+      else if (htab->root.is_relocatable_executable && h->dynindx == -1
+              && h->root.type == bfd_link_hash_new)
+       {
+         /* Output absolute symbols so that we can create relocations
+            against them.  For normal symbols we output a relocation
+            against the section that contains them.  */
+         if (! bfd_elf_link_record_dynamic_symbol (info, h))
+           return FALSE;
+       }
+
     }
   else
     {
@@ -5686,6 +5710,55 @@ elf32_arm_swap_symbol_out (bfd *abfd,
   bfd_elf32_swap_symbol_out (abfd, src, cdst, shndx);
 }
 
+/* Add the PT_ARM_EXIDX program header.  */
+
+static bfd_boolean
+elf32_arm_modify_segment_map (bfd *abfd, 
+                             struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  struct elf_segment_map *m;
+  asection *sec;
+
+  sec = bfd_get_section_by_name (abfd, ".ARM.exidx");
+  if (sec != NULL && (sec->flags & SEC_LOAD) != 0)
+    {
+      /* If there is already a PT_ARM_EXIDX header, then we do not
+        want to add another one.  This situation arises when running
+        "strip"; the input binary already has the header.  */
+      m = elf_tdata (abfd)->segment_map;
+      while (m && m->p_type != PT_ARM_EXIDX)
+       m = m->next;
+      if (!m)
+       {
+         m = bfd_zalloc (abfd, sizeof (struct elf_segment_map));
+         if (m == NULL)
+           return FALSE;
+         m->p_type = PT_ARM_EXIDX;
+         m->count = 1;
+         m->sections[0] = sec;
+
+         m->next = elf_tdata (abfd)->segment_map;
+         elf_tdata (abfd)->segment_map = m;
+       }
+    }
+
+  return TRUE;
+}
+
+/* We may add a PT_ARM_EXIDX program header.  */
+
+static int
+elf32_arm_additional_program_headers (bfd *abfd)
+{
+  asection *sec;
+
+  sec = bfd_get_section_by_name (abfd, ".ARM.exidx");
+  if (sec != NULL && (sec->flags & SEC_LOAD) != 0)
+    return 1;
+  else
+    return 0;
+}
+
 /* We use this to override swap_symbol_in and swap_symbol_out.  */
 const struct elf_size_info elf32_arm_size_info = {
   sizeof (Elf32_External_Ehdr),
@@ -5756,6 +5829,9 @@ const struct elf_size_info elf32_arm_size_info = {
 #define elf_backend_copy_indirect_symbol        elf32_arm_copy_indirect_symbol
 #define elf_backend_symbol_processing          elf32_arm_symbol_processing
 #define elf_backend_size_info                  elf32_arm_size_info
+#define elf_backend_modify_segment_map         elf32_arm_modify_segment_map
+#define elf_backend_additional_program_headers \
+  elf32_arm_additional_program_headers
 
 #define elf_backend_can_refcount    1
 #define elf_backend_can_gc_sections 1
@@ -5846,6 +5922,7 @@ elf32_arm_symbian_link_hash_table_create (bfd *abfd)
       /* The PLT entries are each three instructions.  */
       htab->plt_entry_size = 4 * NUM_ELEM (elf32_arm_symbian_plt_entry);
       htab->symbian_p = 1;
+      htab->root.is_relocatable_executable = 1;
     }
   return ret;
 }     
@@ -5889,8 +5966,7 @@ elf32_arm_symbian_begin_write_processing (bfd *abfd,
 
 static bfd_boolean
 elf32_arm_symbian_modify_segment_map (bfd *abfd, 
-                                     struct bfd_link_info *info 
-                                       ATTRIBUTE_UNUSED)
+                                     struct bfd_link_info *info)
 {
   struct elf_segment_map *m;
   asection *dynsec;
@@ -5907,7 +5983,8 @@ elf32_arm_symbian_modify_segment_map (bfd *abfd,
       elf_tdata (abfd)->segment_map = m;
     }
 
-  return TRUE;
+  /* Also call the generic arm routine.  */
+  return elf32_arm_modify_segment_map (abfd, info);
 }
 
 #undef elf32_bed
This page took 0.026312 seconds and 4 git commands to generate.